Типы данных C - C data types

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

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

Основные типы

Основные типы

Язык C предоставляет четыре основных арифметических спецификатора типа char , int , float и double , а также модификаторы signed , unsigned , short и long . В следующей таблице перечислены допустимые комбинации при указании большого набора объявлений, зависящих от размера хранилища.

Тип Объяснение Минимальный размер (бит) Спецификатор формата
char Наименьшая адресуемая единица машины, которая может содержать базовый набор символов. Это целочисленный тип. Фактический тип может быть подписанным или беззнаковым. Он содержит биты CHAR_BIT. 8 %c
signed char Того же размера, что и char , но с гарантированной подписью. Может содержать как минимум диапазон [-127, +127]. 8 %c (или %hhiдля числового вывода)
unsigned char Имеет тот же размер, что и char , но гарантированно без знака. Содержит как минимум диапазон [0, 255]. 8 %c (или %hhuдля числового вывода)
short
short int
signed short
signed short int
Короткий знаковый целочисленный тип. Может содержать как минимум диапазон [-32,767, +32,767]. 16 %hi или %hd
unsigned short
unsigned short int
Короткий беззнаковый целочисленный тип. Содержит как минимум диапазон [0, 65 535]. 16 %hu
int
signed
signed int
Базовый целочисленный тип со знаком. Может содержать как минимум диапазон [-32,767, +32,767]. 16 %i или %d
unsigned
unsigned int
Базовый беззнаковый целочисленный тип. Содержит как минимум диапазон [0, 65 535]. 16 %u
long
long int
signed long
signed long int
Длинный знаковый целочисленный тип. Способен содержать как минимум диапазон [−2 147 483 647, +2 147 483 647]. 32 %li или %ld
unsigned long
unsigned long int
Длинный беззнаковый целочисленный тип. Может содержать по крайней мере диапазон [0, 4 294 967 295]. 32 %lu
long long
long long int
signed long long
signed long long int
Длинный длинный знаковый целочисленный тип. Способен содержать по крайней мере диапазон [-9,223,372,036,854,775,807, +9,223,372,036,854,775,807]. Указан начиная с версии стандарта C99 . 64 %lli или %lld
unsigned long long
unsigned long long int
Длинный длинный беззнаковый целочисленный тип. Содержит как минимум диапазон [0, +18,446,744,073,709,551,615]. Указан начиная с версии стандарта C99 . 64 %llu
float Реальный тип с плавающей запятой, обычно называемый типом с плавающей запятой одинарной точности. Фактические свойства не указаны (кроме минимальных ограничений); однако в большинстве систем это двоичный формат с плавающей запятой одинарной точности IEEE 754 (32 бита). Этот формат требуется дополнительным Приложением F «Арифметика с плавающей запятой МЭК 60559». Преобразование из текста:
double Реальный тип с плавающей запятой, обычно называемый типом с плавающей запятой двойной точности. Фактические свойства не указаны (кроме минимальных ограничений); однако в большинстве систем это двоичный формат с плавающей запятой двойной точности IEEE 754 (64 бита). Этот формат требуется дополнительным Приложением F «Арифметика с плавающей запятой МЭК 60559».
long double Реальный тип с плавающей запятой, обычно отображаемый в формат чисел с плавающей запятой повышенной точности . Фактические свойства не указаны. Это может быть формат x86 с плавающей запятой расширенной точности (80 бит, но обычно 96 бит или 128 бит в памяти с байтами заполнения ), не-IEEE « double-double » (128 бит), IEEE 754 с плавающей запятой четверной точности -точечный формат (128 бит) или то же, что и двойной. Подробнее читайте в статье о длинном дабл . %Lf %LF
%Lg %LG
%Le %LE
%La %LA

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

Требования к соотношению заключаются в том, чтобы long longне было меньше чем long, что не меньше чем int, которое не меньше чем short. Поскольку charразмер всегда является минимально поддерживаемым типом данных, никакие другие типы данных (кроме битовых полей ) не могут быть меньше.

Минимальный размер для charсоставляет 8 бит, минимальный размер для shortи intсоставляет 16 бит, поскольку longон составляет 32 бита и long longдолжен содержать не менее 64 бит.

Тип intдолжен быть целочисленным типом, с которым целевой процессор наиболее эффективно работает. Это обеспечивает большую гибкость: например, все типы могут быть 64-битными. Однако популярны несколько различных схем целочисленной ширины (моделей данных). Поскольку модель данных определяет способ взаимодействия различных программ, в интерфейсе приложения данной операционной системы используется единообразная модель данных.

На практике charобычно имеет размер 8 бит и shortобычно имеет размер 16 бит (как и их беззнаковые аналоги). Это справедливо для самых разных платформ, таких как SunOS  4 Unix 1990-х годов , Microsoft MS-DOS , современный Linux и Microchip MCC18 для встроенных 8-битных микроконтроллеров PIC . POSIX требует, charчтобы размер был ровно 8 бит.

Различные правила в стандарте C делают unsigned charосновной тип, используемый для массивов, подходящим для хранения произвольных объектов, не являющихся битовыми полями: отсутствие в нем битов заполнения и представления ловушек, определение представления объекта и возможность наложения псевдонимов.

Фактический размер и поведение типов с плавающей запятой также зависят от реализации. Единственная гарантия - long doubleне меньше double, что не меньше float. Обычно используются 32-битные и 64-битные двоичные форматы с плавающей запятой IEEE 754 .

Стандарт C99 включает новые реальные типы с плавающей запятой float_tи double_t, определенные в <math.h>. Они соответствуют типам, используемым для промежуточных результатов выражений с плавающей запятой, когда FLT_EVAL_METHODэто 0, 1 или 2. Эти типы могут быть шире, чем long double.

C99 также добавил сложные типы: float _Complex, double _Complex, long double _Complex.

Логический тип

C99 добавил логический (истина / ложь) тип _Bool. Кроме того, <stdbool.h>заголовок определяется boolкак удобный псевдоним для этого типа, а также предоставляет макросы для trueи false. _Boolфункционирует аналогично обычному целочисленному типу, за одним исключением: любые присвоения a _Bool, отличные от 0 (false), сохраняются как 1 (true). Такое поведение существует, чтобы избежать целочисленных переполнений в неявных сужающих преобразованиях. Например, в следующем коде:

unsigned char b = 256;

if (b) {
	/* do something */
}

Переменная bпринимает значение false, если unsigned charимеет размер 8 бит. Это связано с тем, что значение 256 не соответствует типу данных, в результате чего используются его младшие 8 бит, что приводит к нулевому значению. Однако изменение типа заставляет предыдущий код вести себя нормально:

_Bool b = 256;

if (b) {
	/* do something */
}

Тип _Bool также гарантирует, что истинные значения всегда равны друг другу:

_Bool a = 1, b = 2;

if (a == b) {
	/* do something */
}

Типы разницы в размере и указателе

Спецификация языка C включает typedef s size_tи ptrdiff_tдля представления величин, связанных с памятью. Их размер определяется в соответствии с арифметическими возможностями целевого процессора, а не возможностями памяти, такими как доступное адресное пространство. Оба этих типа определены в <stddef.h>заголовке ( cstddefв C ++).

size_tпредставляет собой целочисленный тип без знака, используемый для представления размера любого объекта (включая массивы) в конкретной реализации. Оператор sizeof возвращает значение типа size_t. Максимальный размер size_tпредоставляется через SIZE_MAXмакроконстанту, которая определяется в заголовке ( заголовок в C ++). гарантированно будет иметь ширину не менее 16 бит. Кроме того, POSIX включает целочисленный тип со знаком той же ширины, что и . <stdint.h>cstdintsize_tssize_tsize_t

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

Интерфейс к свойствам основных типов

Информация о фактических свойствах, таких как размер, основных арифметических типов предоставляется через макроконстанты в двух заголовках: <limits.h>заголовок ( climitsзаголовок в C ++) определяет макросы для целочисленных типов, а <float.h>заголовок ( cfloatзаголовок в C ++) определяет макросы для типов с плавающей запятой. . Фактические значения зависят от реализации.

Свойства целочисленных типов

  • CHAR_BIT - размер типа char в битах (не менее 8 бит)
  • SCHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN(C99) - минимально возможное значение подписанных целочисленных типов: подписан полукокс, подписанных короткий, подписанные межды, подписанные долго, подписанные долго долго
  • SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX(C99) - максимально возможное значение подписанных целочисленных типов: подписан полукокс, подписанных короткий, подписанные межды, подписанные долго, подписанные долго долго
  • UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, ULLONG_MAX(С99) - максимально возможное значение целых беззнаковых типов: беззнаковых символов, без знака Короче говоря, без знака Int, неподписанные долго, без знака долго долго
  • CHAR_MIN - минимально возможное значение char
  • CHAR_MAX - максимально возможное значение char
  • MB_LEN_MAX - максимальное количество байтов в многобайтовом символе

Свойства типов с плавающей запятой

  • FLT_MIN, DBL_MIN, LDBL_MIN- минимальное нормализованы положительное значение с плавающей точкой, двойной, двойной длиной соответственно
  • FLT_TRUE_MIN, DBL_TRUE_MIN, LDBL_TRUE_MIN(С11) - минимальное значение положительного поплавка, двойной, двойная длиной соответственно
  • FLT_MAX, DBL_MAX, LDBL_MAX- максимальное конечное значение поплавка, двойной, длинный двойной, соответственно ,
  • FLT_ROUNDS - режим округления для операций с плавающей запятой
  • FLT_EVAL_METHOD (C99) - метод оценки выражений, включающих различные типы с плавающей запятой
  • FLT_RADIX - основание экспоненты в типах с плавающей запятой
  • FLT_DIG, DBL_DIG, LDBL_DIG- число десятичных цифр , которые могут быть представлены без потери точности при обращении, двойной, длинный двойной, соответственно ,
  • FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON- разница между 1,0 и следующим представимым значением поплавка, двойной, длинным двойной, соответственно ,
  • FLT_MANT_DIG, DBL_MANT_DIG, LDBL_MANT_DIG- число FLT_RADIX-BASE цифр с плавающей точкой мантиссы для типов с плавающей точкой, двойной, длинный двойной, соответственно ,
  • FLT_MIN_EXP, DBL_MIN_EXP, LDBL_MIN_EXP- минимальное отрицательное целое число такое , что FLT_RADIXповышается до мощности на единицу меньше числа является нормализованной с плавающей точкой, двойной, длинный двойной, соответственно ,
  • FLT_MIN_10_EXP, DBL_MIN_10_EXP, LDBL_MIN_10_EXP- минимальное отрицательное целое число , такое , что 10 в этой силы является нормализованной с плавающей точкой, двойной, длинный двойной, соответственно ,
  • FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP- максимальное положительное целое число , такое , что FLT_RADIXповышают до мощности на единицу меньше числа является нормализованной с плавающей точкой, двойной, длинный двойной, соответственно ,
  • FLT_MAX_10_EXP, DBL_MAX_10_EXP, LDBL_MAX_10_EXP- максимальное положительное целое число , такое , что 10 в этой силы является нормализованной с плавающей точкой, двойной, длинный двойной, соответственно ,
  • DECIMAL_DIG(C99) - минимальное количество десятичных цифр, такое, что любое число самого широкого поддерживаемого типа с плавающей запятой может быть представлено в десятичном виде с точностью до DECIMAL_DIGцифр и считано в исходном типе с плавающей запятой без изменения его значения. DECIMAL_DIGне менее 10.

Целочисленные типы фиксированной ширины

Стандарт C99 включает определения нескольких новых целочисленных типов для повышения переносимости программ. Уже доступных базовых целочисленных типов было сочтено недостаточным, поскольку их фактические размеры определяются реализацией и могут различаться в разных системах. Новые типы особенно полезны во встроенных средах, где оборудование обычно поддерживает только несколько типов, и эта поддержка варьируется в зависимости от среды. Все новые типы определены в <inttypes.h>заголовке ( cinttypesзаголовок в C ++), а также доступны в <stdint.h>заголовке ( cstdintзаголовок в C ++). Типы можно сгруппировать в следующие категории:

  • Целочисленные типы точной ширины, которые гарантированно имеют одинаковое количество бит n во всех реализациях. Включается только в том случае, если это доступно в реализации.
  • Целочисленные типы с наименьшей шириной, которые гарантированно будут наименьшим типом, доступным в реализации, который имеет как минимум указанное количество n бит. Гарантированно указывается не менее N = 8,16,32,64.
  • Самые быстрые целочисленные типы, которые гарантированно являются самыми быстрыми целочисленными типами, доступными в реализации, которые имеют как минимум заданное количество n битов. Гарантированно указывается не менее N = 8,16,32,64.
  • Целочисленные типы указателей, которые гарантированно могут содержать указатель. Включается только в том случае, если это доступно в реализации.
  • Целочисленные типы максимальной ширины, которые гарантированно будут наибольшим целочисленным типом в реализации.

В следующей таблице приведены типы и интерфейс для получения сведений о реализации ( n означает количество битов):

Категория типа Подписанные типы Беззнаковые типы
Тип Минимальное значение Максимальное значение Тип Минимальное значение Максимальное значение
Точная ширина intn_t INTn_MIN INTn_MAX uintn_t 0 UINTn_MAX
Наименьшая ширина int_leastn_t INT_LEASTn_MIN INT_LEASTn_MAX uint_leastn_t 0 UINT_LEASTn_MAX
Самый быстрый int_fastn_t INT_FASTn_MIN INT_FASTn_MAX uint_fastn_t 0 UINT_FASTn_MAX
Указатель intptr_t INTPTR_MIN INTPTR_MAX uintptr_t 0 UINTPTR_MAX
Максимальная ширина intmax_t INTMAX_MIN INTMAX_MAX uintmax_t 0 UINTMAX_MAX

Спецификаторы формата printf и scanf

<inttypes.h>Заголовка ( cinttypesв C ++) обеспечивает функции , которые повышают функциональность типов , определенных в <stdint.h>заголовке. Он определяет макросы для Printf форматной строки и формата зсапЕ строки спецификаторов , соответствующих типов , определенных в <stdint.h>и несколько функций для работы с intmax_tи uintmax_tтипами. Этот заголовок был добавлен в C99 .

Строка формата printf

Макросы в формате . Здесь {fmt} определяет форматирование вывода и может быть одним из (десятичного), (шестнадцатеричного), (восьмеричного), (беззнакового) и (целого). {тип} определяет тип аргумента и является одним из , , , , , где соответствует числу битов в аргументе. PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Строка формата scanf

Макросы в формате . Здесь {fmt} определяет форматирование вывода и может быть одним из (десятичного), (шестнадцатеричного), (восьмеричного), (беззнакового) и (целого). {тип} определяет тип аргумента и является одним из , , , , , где соответствует числу битов в аргументе. SCN{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Функции

Дополнительные типы с плавающей запятой

Подобно целочисленным типам фиксированной ширины, ISO / IEC TS 18661 определяет типы с плавающей запятой для обмена IEEE 754 и расширенные форматы в двоичном и десятичном формате:

  • _FloatN для двоичных форматов обмена;
  • _DecimalN для десятичных форматов обмена;
  • _FloatNx для двоичных расширенных форматов;
  • _DecimalNx для расширенных десятичных форматов.

Структуры

Структуры объединяют хранилище нескольких элементов данных потенциально разных типов данных в один блок памяти, на который ссылается одна переменная. В следующем примере объявляется тип данных, struct birthdayсодержащий имя и день рождения человека. За определением структуры следует объявление переменной, Johnкоторая выделяет необходимое хранилище.

struct birthday {
	char name[20];
	int day;
	int month;
	int year;
};

struct birthday John;

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

Структура, содержащая указатель на структуру собственного типа, обычно используется для построения связанных структур данных :

struct node {
	int val;
	struct node *next;
};

Массивы

Для каждого типа T, кроме типов void и function, существуют типы «массив Nэлементов типа T» . Массив - это набор значений одного типа, непрерывно хранящихся в памяти. Массив размера Nиндексируется целыми числами от 0до включительно N−1. Вот краткий пример:

int cat[10];  // array of 10 elements, each of type int

Массивы можно инициализировать с помощью составного инициализатора, но не назначать. Массивы передаются функциям путем передачи указателя на первый элемент. Многомерные массивы определяются как «массив массивов…» , и все, кроме самого внешнего измерения, должны иметь размер, постоянный во время компиляции:

int a[10][8];  // array of 10 elements, each of type 'array of 8 int elements'

Указатели

Каждому типу данных Tсоответствует указатель наT тип . Указатель представляет собой тип данных , который содержит адрес места хранения переменной определенного типа. Они объявляются с помощью *декларатора типа asterisk ( ), следующего за базовым типом хранилища и перед именем переменной. Пробелы до или после звездочки не обязательны.

char *square;
long *circle;
int *oval;

Указатели также могут быть объявлены для типов данных указателей, создавая таким образом несколько косвенных указателей, таких как char ** и int *** , включая указатели на типы массивов. Последние менее распространены, чем массив указателей, и их синтаксис может сбивать с толку:

char *pc[10];   // array of 10 elements of 'pointer to char'
char (*pa)[10]; // pointer to a 10-element array of char

Для элемента pcтребуется десять блоков памяти размером с указательchar (обычно 40 или 80 байтов на обычных платформах), но элемент paпредставляет собой только один указатель (размер 4 или 8 байтов), а данные, на которые он ссылается, представляют собой массив из десяти байтов. ( ). sizeof *pa == 10

Союзы

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

union {
	int i;
	float f;
	struct {
		unsigned int u;
		double d;
	} s;
} u;

Общий размер u- это размер, u.sкоторый является суммой размеров u.s.uи, u.s.dпоскольку sон больше, чем оба iи f. При назначении чему-либо u.iнекоторые части u.fмогут быть сохранены, если они u.iменьше, чем u.f.

Чтение из члена объединения - это не то же самое, что приведение, поскольку значение члена не конвертируется, а просто читается.

Указатели на функции

Указатели функций позволяют ссылаться на функции с определенной сигнатурой. Например, чтобы сохранить absв переменной адрес стандартной функции my_int_f:

int (*my_int_f)(int) = &abs;
// the & operator can be omitted, but makes clear that the "address of" abs is used here

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

Квалификаторы типа

Вышеупомянутые типы могут быть дополнительно охарактеризованы квалификаторами типов , в результате чего получается квалифицированный тип . По состоянию на 2014 год и C11 , в стандарте C есть четыре квалификатора типа: const( C89 ), volatile( C89 ), restrict( C99 ) и _Atomic( C11 ) - последний имеет частное имя, чтобы избежать конфликтов с именами пользователей, но более обычное имя atomicможет использоваться, если <stdatomic.h>заголовок включен. Из них, constбезусловно, самый известный и наиболее используемый, он появляется в стандартной библиотеке и встречается при любом значительном использовании языка C, который должен удовлетворять константной корректности . Другие квалификаторы используются для низкоуровневого программирования и, хотя и широко используются там, редко используются типичными программистами.

Смотрите также

использованная литература