Типы данных

В языке Си строгая статическая типизация, в отличии от Python, в котором допустимо создать переменную типа «строка», а в ходе выполнения программы переделать ее в число с плавающей запятой. В Си, если вы создали переменную a как целое число, записать в нее вещественное число получится только с приведением типов (т.е. с потерей дробной части), и то только в случае, если размер целочисленной переменной в байтах больше или равен размеру переменной вещественного типа.

{модификатор(ы)} [спецификатор типа] [список имен];

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

int count = 0;
unsigned char param_a, param_b;
static volatile float temperature = 0.0f;
void *ptr;

Имена переменных имеют некоторые ограничения: они не могут начинаться с цифр или содержать спецсимволы (!, @ и т. д.) Знак подчеркивания _ считается буквой и часто используется для улучшения читаемости.

bool isdigit(char ch);  // bad
bool is_digit(char ch); // good
bool isDigit(char ch);  // CamelCase, C++ style

Данный символ можно использовать и в начале имени, однако в основной программе лучше так не делать, так как по договоренности такое именование принято в сторонних библиотеках. Ниже приведен пример системной функции из библиотеки CMSIS.

static __INLINE void __NOP()          { __ASM volatile ("nop"); }

Регистр также имеет значение, поэтому переменные с именами X и x будут разными.

ТипРазмерПримечание
void0 байтБуквально означает «ничего». Появился в стандарте c89 и является самым необычным типом. Нельзя создать переменную с этим спецификатором, однако можно использовать его для функций, которые ничего не возвращают, либо как тип указателя (об этом позже).
_Bool1 байтДанный тип появился начиная со стандарта c99, в файле <stdbool.h> для него определен псевдоним bool, а также макросы true (истина) и false (ложь). Любое вписанное ненулевое значение хранится как 1.
char1 байтПрименяется для представления символьной информации. Занимает 8 бит и кодирует печатные и непечатные символы (например пробел, перевод каретки и т.д.) по таблице символов ASCII (абр. American Standard Code for Information Interchange), где первые 128 позиций являются стандартными и неизменяемыми, а остальные отводятся на региональные расширения, зависящие от особенностей языка. Есть и другие системы кодов, например EBCDIC (англ. Extended Binary Coded Decimal Interchange Code).
int4 байтаИспользуется для описания целочисленных переменных, по умолчанию является знаковым и для 32-битной системы занимает 4 байта (32 бита).
float4 байтаИспользуется для описания чисел с плавающей запятой одинарной точности.
double8 байтДля более точных расчетов можно использовать число с плавающей точкой двойной точности.

Размер (в байтах, а значит, и диапазон значений) переменных зависит от разрядности системы. Так, int в 16-разрядном микроконтроллере может занимать 16 бит, а в 32-разрядном будет занимать 32 бита. Следовательно, код, написанный под одну платформу, может некорректно работать на другой. Максимальные и минимальные значения типов можно найти в файле <limits.h>. Тема циклов еще впереди, однако подумайте, в чём может быть проблема при выполнении следующего кода на stm8 и почему он нормально отработает на stm32? Код в фигурных скобках будет выполнятся 65700 раз. Ключевое слово unsigned указывает на то, что переменная может хранить только не отрицательные числа.

for (unsigned int i = 0; i < 65700; i++) {
    // do something
}

Правильно! Произойдет переполнение: так как unsigned int на stm8 равняется всего 16 битам, максимальное значение, которое может принять i, равняется 216-1, что меньше, чем 65700. При достижении максимального значения переменная перейдет в ноль, и счет начнется заново, поэтому данный цикл никогда не завершится.

В стандарте c99 определены дополнительные типы целочисленных переменных, которые можно найти в <inttype.h> (или через <stdint.h>). Если необходимо задать точный размер переменной, можно использовать типы intN_t / uintN_t (где N = { 8, 16, 32, 64 }). Приставка fast (int_fastN_t / uint_fastN_t) позволит использовать максимально производительную переменную на данный платформе (подробнее в главе об оптимизации). Приставка least (int_leastN_t / uint_leastN_t) гарантирует минимальный размер с учетом платформы, но точно не меньший, чем N. Также имеются типы для указателей intptr_t / uintptr_t, которые гарантируют, что с их помощью можно хранить адрес.


Изменено:

Язык Си: 3 комментария

  1. >Вместо нуля может быть почти любой другой символ. Плюс и минус работают по-другому. Для выравнивания числа по по левому краю, а не по правому, перед числом нужно поставить знак минус.
    Лишне по

  2. Термин «регистр ядра» довольно специфичен. Звучит не привычно. А почему не использовать термин CPU или процессор или на худой конец микроконтроллер?

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.