Типы данных

В языке Си строгая статическая типизация, в отличии от 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, которые гарантируют, что с их помощью можно хранить адрес.

0

Изменено:

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

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

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

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

    0

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

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

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