Скачиваний:
2
Добавлен:
03.01.2024
Размер:
2.34 Mб
Скачать

Резюме по языку Си

Типизация: статическая слабая явная.

«Простые» типы:

_Bool (bool) – начиная с С99 - #include <stdbool.h>

char, signed char, unsigned char

short

int

long

long long

float, double, long double

void

указатели

Композитные: массивы, структуры, объединения

Функции

Выражения

Подробности:

Читать Стандарт языка (С89, С99, )

Искать на stackoverflow.com

Просто писать программы!

Статическая / динамическая типизация. Статическая определяется тем, что конечные типы переменных и функций устанавливаются на этапе компиляции. Т.е. уже компилятор на 100% уверен, какой тип где находится. В динамической типизации все типы выясняются уже во время выполнения программы.

Примеры:

Статическая: Cи, Java, C#;

Динамическая: Python, JavaScript, Ruby.

Сильная / слабая типизация (также иногда говорят строгая /

нестрогая). Сильная типизация выделяется тем, что язык не позволяет смешивать в выражениях различные типы и не выполняет автоматические неявные преобразования, например нельзя вычесть из строки множество. Языки со слабой типизацией выполняют множество неявных преобразований автоматически, даже если может произойти потеря точности или преобразование неоднозначно.

Примеры:

Сильная: Java, Python, Haskell, Lisp; Слабая: Cи, JavaScript, Visual Basic, PHP.

Явная / неявная типизация. Явно-типизированные языки отличаются тем, что тип новых переменных / функций / их аргументов нужно задавать явно. Соответственно языки с неявной типизацией перекладывают эту задачу на компилятор / интерпретатор.

Примеры:

Явная: C++, D, C#

Неявная: PHP, Lua, JavaScript

Также нужно заметить, что все эти категории пересекаются, например язык Cи имеет статическую слабую явную типизацию, а

язык Python — динамическую сильную неявную.

21

 

 

«Чудеса» Си. И как с этим жить

«Чудо» первое: размеры типов

«Чудо» второе: поведение

Тип:

Размер в битах:

 

char

не менее 8

 

short

не менее 16

 

int

не менее 16

 

long

не менее 32

 

long long

не менее 64

 

Как жить с этим чудом?

Использовать типы с известной длиной!

#include <stdint.h>

char – чтобы хранить символы (а не числа)

int8_t – знаковый 8 бит

uint8_t – беззнаковый 8

int16_t – знаковый 16 бит

uint16_t – беззнаковый 16 бит и т.д. вплоть до 64

Компиляторы не всегда предупреждают Компиляторы не всегда следуют стандарту

Как жить с этим чудом?

Не выключать предупреждения (warning)

ЧИТАТЬ предупреждения! Ценить, что они вообще есть.

Помнить, что отсутствие предупреждений не означает, что все хорошо.

22

«Чудеса» Си. И как с этим жить

«Чудо» третье, неожиданное

Если поведение определенное, это еще не значит, что оно очевидное.

Примеры:

Правила неявного преобразования типов

Приоритеты операторов

Арифметика с плавающей точкой (не только в Си!)

Макросы

Указатели, указатели, указатели..

Компиляция с оптимизацией усиливают чудеса!

Как жить с чудесами?

Учиться, учиться и еще раз учиться.

Или искать другой язык.

В каждом языке есть свои чудеса!

Аргументы критиков Cи

Компиляторы не всегда предупреждают

Компиляторы не всегда следуют стандарту

Как жить с этим чудом?

Не выключать предупреждения (warning)

ЧИТАТЬ предупреждения! Ценить, что они вообще есть.

Помнить, что отсутствие предупреждений не означает, что все хорошо.

Абстрактная машина языка слишком похожа на устаревшую архитектуру PDP-11, которая давно уже не соответствует устройству популярных современных процессоров.

Несоответствие абстрактной машины устройству реальных машин усложняет разработку оптимизирующих компиляторов языка.

Неполнота и сложность стандарта языка Си ведут к разночтениям в реализациях стандарта.

Доминирование -подобных языков не позволяет исследовать альтернативные архитектуры процессоров.

Архаичная библиотека функций, запутанный и противоречивый стандарт, грубые ошибки в дизайне.

Но, судя по всему, кое-что создатели языка всё же сделали правильно.

Так или иначе, по-прежнему нужен язык низкого уровня, причём построенный именно для популярных фоннеймановских компьютеров.

И пускай «устарел», но, видимо, любому его преемнику всё равно придётся отталкиваться от тех же самых принципов.

23

…и ещё одна классификация типов данных Си

Типы данных Си

Адресные

Структурированные

Указатель

Ссылка (С++)

Нерегулярные

Регулярные

Простые

Целые

Bool

void

С плавающей точкой

(Си99)

 

 

 

signed

unsigned

enum

float

double

long

 

 

 

double

 

 

 

 

 

char

short

int

long

24

Небольшой список из популярных языков программирования

Язык

 

Типизация

 

 

 

 

 

JavaScript

Динамическая

Слабая

Неявная

 

 

 

 

Ruby

Динамическая

Сильная

Неявна

 

 

 

 

Python

Динамическая

Сильная

Неявная

 

 

 

 

Java

Статическая

Сильная

Явная

 

 

 

 

PHP

Динамическая

Слабая

Неявная

 

 

 

 

Статическая

Слабая

Явная

 

 

 

 

C++

Статическая

Слабая

Явная

 

 

 

 

Perl

Динамическая

Слабая

Неявная

 

 

 

 

Objective-C

Статическая

Слабая

Явная

 

 

 

 

C#

Статическая

Сильная

Явная

 

 

 

 

Haskell

Статическая

Сильная

Неявная

 

 

 

 

Common Lisp

Динамическая

Сильная

Неявная

 

 

 

 

D

Статическая

Сильная

Явная

 

 

 

 

Delphi/Pascal

Статическая

Сильная

Явная

 

 

 

 

Примечания к таблице:

C# — поддерживает динамическую типизацию, посредством специального псевдо-типа dynamic с версии 4.0.

Поддерживает неявную типизацию с помощью dynamic и var.

С++ — после стандарта C++11 получил поддержку неявной типизации с помощью ключевых слов auto и decltype. Поддерживает динамическую типизацию, при использовании библиотеки Boost (boost::any, boost::variant). Имеет черты как сильной так и слабой типизации.

Common Lisp — стандарт предусматривает декларации типов, которые некоторые реализации могут использовать также для статической проверки типов.

D — также поддерживает неявную типизацию.

Delphi/Pascal — поддерживает динамическую типизацию посредством специального типа Variant.

25

Выводы

Система типов — совокупность правил в языках программирования, назначающих свойства, именуемые типами, различным конструкциям, составляющим программу — таким как переменные, выражения, функции или модули.

Основная роль системы типов заключается в уменьшении числа багов в программах посредством определения интерфейсов между различными частями программы и последующей проверки согласованности взаимодействия этих частей.

Эта проверка может происходить статически (на стадии компиляции[en]) или динамически (во время выполнения), а также быть комбинацией обоих видов.

Пример простой системы типов можно видеть в языке Си. Части программы на Си оформляются в виде определений функций. Функции вызывают друг друга.

Интерфейс функции задаёт имя функции и список значений, которые передаются её телу. Вызывающая функция постулирует имя функции, которую хочет вызвать, и имена переменных, хранящих значения, которые требуется передать.

Во время исполнения программы значения помещаются во временное хранилище, и затем исполнение передаётся в тело вызываемой функции. вызываемой функции осуществляет доступ к значениям и использует их.

Если инструкции в теле функции написаны в предположении, что им на обработку должно быть передано целое значение, но вызывающий передал число с плавающей точкой, то вызванная функция вычислит неверный результат.

Компилятор Си проверяет типы, заданные для каждой переданной переменной, в отношении к типам, заданным для каждой переменной в интерфейсе вызываемой функции. Если типы не совпадают, компилятор порождает ошибку времени компиляции.

Технически, система типов назначает тип каждому вычисленному значению и затем, отслеживая последовательность этих вычислений, предпринимает попытку проверить или доказать отсутствие ошибок согласования типов. Конкретная система типов может определять, что именно приводит к ошибке, но обычно целью является предотвращение того, чтобы операции, предполагающие определённые свойства своих параметров, получали параметры, для которых эти операции не имеют смысла — предотвращение логических ошибок. Дополнительно это также предотвращает ошибки адресации памяти.

Системы типов обычно определяются как часть языков программирования и встраиваются в их интерпретаторы и компиляторы. Однако система типов языка может быть расширена посредством специальных инструментов[en], осуществляющих дополнительные проверки на основе исходного синтаксиса типизации в языке.

Компилятор также может использовать статический тип значения для оптимизации хранилища и для выбора алгоритмической реализации операций над этим значением.

Например, во многих компиляторах Си тип float представляется 32 битами, в соответствии со спецификацией IEEE для операций с плавающей точкой одинарной точности. На основании этого будет использоваться специальный набор инструкций микропроцессора для значений этого типа (сложение, умножение и другие операции).

Количество налагаемых на типы ограничений и способ их вычисления определяют типизацию языка. Помимо этого, в случае полиморфизма типов, язык может также задать для каждого типа операцию варьирования конкретных алгоритмов.

Изучением систем типов занимается теория типов, хотя на практике конкретная система типов языка программирования основывается на особенностях архитектуры компьютера, реализации

компилятора и общем образе языка.

26

27

Соседние файлы в папке Лекции