Тип
(См. также арифметические типы для получения подробной информации о большинстве встроенных типов и список утилит, связанных с типами, предоставляемых библиотекой C.)
Объекты, функции и выражения обладают свойством тип, которое определяет интерпретацию двоичного значения, хранящегося в объекте или вычисляемого выражением.
Классификация типов
Система типов C состоит из следующих типов:
- тип
void - базовые типы
- тип
char - целые типы со знаком
- стандартные:
signed char,short,int,long,long long(с C99)
| (с C23) |
| (с C99) |
- целые типы без знака
- стандартные:
_Bool,(с C99)unsigned char,unsigned short,unsigned int,unsigned long,unsigned long long(с C99)
| (с C23) |
| (с C99) |
- типы с плавающей точкой
- вещественные типы с плавающей точкой:
float,double,long double
| (с C23) |
| (с C99) |
- перечисляемые типы
- производные типы
| (с C11) |
Для каждого указанного выше типа могут существовать несколько квалифицированных версий его типа, соответствующих комбинациям одного, двух или всех трех const, volatile и restrict квалификаторов (там, где это разрешено семантикой квалификатора).
Группы типов
- типы объектов: все типы, которые не являются типами функций
- типы символов:
char,signed char,unsigned char - целые типы:
char, типы целых чисел со знаком, типы целых чисел без знака, перечисляемые типы - вещественные типы: целые типы и вещественные типы с плавающей точкой
- арифметические типы: целые типы и типы с плавающей точкой
- скалярные типы: арифметические типы, указатели, и
nullptr_t(с C23) - составные типы: типы массивов и структуры
- производные типы деклараторов: типы массивов, типы функций и типы указателей
Конструирование полного типа объекта, такое что количество байт в его представлении объекта не может быть представлено типом size_t (т.е. результатом типа оператора sizeof), в том числе формирование такого типа VLA во время выполнения,(с C99) является неопределённым поведением.
Совместимые типы
В программе C объявления, относящиеся к одному объекту или функции в разных единицах трансляции, не обязательно должны использовать один и тот же тип. Они должны использовать достаточно похожие типы, формально известные как совместимые типы. То же самое относится к вызовам функций и доступам к lvalue; типы аргументов должны быть совместимы с типами параметров, а тип выражения lvalue должен быть совместим с типом объекта, к которому осуществляется доступ.
Типы T и U совместимы, если
- они являются одним и тем же типом (то же имя или псевдонимы, введённые с помощью
typedef) - они являются идентичными cvr-квалифицированными версиями совместимых неквалифицированных типов
- они являются указателями и указывают на совместимые типы
- они являются массивами, и
- их типы элементов совместимы, и
- если у обоих есть постоянный размер, этот размер одинаков. Примечание: массивы с неизвестным размером совместимы с любым массивом совместимого типа элемента. VLA совместим с любым массивом совместимого типа элемента.(с C99)
- они являются структурами/объединениями/перечислениями, и
- (C99)если один объявлен с тегом, другой также должен быть объявлен с тем же тегом.
- если оба являются полными типами, их члены должны соответствовать по количеству, быть объявлены со совместимыми типами и иметь совпадающие имена.
- дополнительно, если они являются перечислениями, соответствующие члены также должны иметь одинаковые значения.
- дополнительно, если они являются структурами или объединениями,
- Соответствующие члены должны быть объявлены в том же порядке (только для структур)
- Соответствующие битовые поля должны иметь одинаковую ширину.
- один является перечисляемым типом, а другой — базовым типом этого перечисления
- они являются типами функций, и
- их возвращаемые типы совместимы
- они оба используют списки параметров, количество параметров (включая использование многоточия) одинаково, и соответствующий параметр после применения корректировок типа массива-указатель и функции-указатель и после удаления квалификаторов верхнего уровня имеет совместимые типы
| (до C23) |
Тип char не совместим с signed char и не совместим с unsigned char.
Если два объявления относятся к одному объекту или функции и не используют совместимые типы, поведение программы неопределено.
// Translation Unit 1
struct S { int a; };
extern struct S *x; // compatible with TU2's x, but not with TU3's x
// Translation Unit 2
struct S;
extern struct S *x; // compatible with both x's
// Translation Unit 3
struct S { float a; };
extern struct S *x; // compatible with TU2's x, but not with TU1's x
// the behavior is undefined// Translation Unit 1
#include <stdio.h>
struct s { int i; }; // compatible with TU3's s, but not TU2's
extern struct s x = {0}; // compatible with TU3's x
extern void f(void); // compatible with TU2's f
int main()
{
f();
return x.i;
}
// Translation Unit 2
struct s { float f; }; // compatible with TU4's s, but not TU1's s
extern struct s y = {3.14}; // compatible with TU4's y
void f() // compatible with TU1's f
{
return;
}
// Translation Unit 3
struct s { int i; }; // compatible with TU1's s, but not TU2's s
extern struct s x; // compatible with TU1's x
// Translation Unit 4
struct s { float f; }; // compatible with TU2's s, but not TU1's s
extern struct s y; // compatible with TU2's y
// the behavior is well-defined: only multiple declarations
// of objects and functions must have compatible types, not the types themselvesПримечание: C++ не имеет понятия совместимых типов. Программа на C, которая объявляет два типа, которые совместимы, но не идентичны в разных единицах трансляции, не является допустимой программой на C++.
Составные типы
Составной тип может быть сконструирован из двух совместимых типов; это тип, совместимый с обоими типами и удовлетворяющий следующим условиям:
- Если оба типа являются типами массивов, применяются следующие правила:
- Если один тип является массивом с известным постоянным размером, составной тип является массивом этого размера.
| (с C99) |
- В противном случае оба типа являются массивами неизвестного размера, и составной тип является массивом неизвестного размера.
| (до C23) |
- Если оба типа являются типами функций со списками типов параметров, тип каждого параметра в составном списке типов параметров является составным типом соответствующих параметров.
Эти правила применяются рекурсивно к типам, из которых происходят два типа.
// Given the following two file scope declarations: int f(int (*)(), double (*)[3]); int f(int (*)(char *), double (*)[]); // C23: Error: conflicting types for 'f' // The resulting composite type for the function is: int f(int (*)(char *), double (*)[3]);
Для идентификатора с внутренней или внешней связью, объявленного в области видимости, в которой ранее объявлено то же самое имя, если предыдущее объявление указывает внутреннюю или внешнюю связь, тип идентификатора при последующем объявлении становится составным типом.
Неполные типы
Неполный тип — это тип объекта, у которого недостаточно информации для определения размера объектов этого типа. Неполный тип может быть завершен на каком-то этапе трансляции.
Следующие типы являются неполными:
- тип
void. Этот тип не может быть завершен. - тип массива неизвестного размера. Он может быть завершен последующим объявлением, в котором указан размер.
extern char a[]; // the type of a is incomplete (this typically appears in a header) char a[10]; // the type of a is now complete (this typically appears in a source file)
- тип структуры или объединения неизвестного содержимого. Он может быть завершен объявлением той же структуры или объединения, которое определяет его содержимое позднее в той же области видимости.
struct node
{
struct node *next; // struct node is incomplete at this point
}; // struct node is complete at this pointИмена типов
Тип может потребоваться назвать в контексте, отличном от объявления. В этих ситуациях используется имя типа, которое грамматически точно такое же, как список спецификаторов типа и квалификаторов типа, за которым следует декларатор (см. объявления), как если бы он использовался для объявления одного объекта или функции этого типа, за исключением того, что идентификатор опущен:
int n; // declaration of an int
sizeof(int); // use of type name
int *a[3]; // declaration of an array of 3 pointers to int
sizeof(int *[3]); // use of type name
int (*p)[3]; // declaration of a pointer to array of 3 int
sizeof(int (*)[3]); // use of type name
int (*a)[*] // declaration of pointer to VLA (in a function parameter)
sizeof(int (*)[*]) // use of type name (in a function parameter)
int *f(void); // declaration of function
sizeof(int *(void)); // use of type name
int (*p)(void); // declaration of pointer to function
sizeof(int (*)(void)); // use of type name
int (*const a[])(unsigned int, ...) = {0}; // array of pointers to functions
sizeof(int (*const [])(unsigned int, ...)); // use of type nameЗа исключением лишних скобок вокруг идентификатора, которые имеют значение в имени типа и представляют «функцию без указания параметров»:
int (n); // declares n of type int sizeof(int ()); // uses type "function returning int"
Имена типов используются в следующих ситуациях:
| (с C99) | |
| (с C11) |
Имя типа может ввести новый тип:
void* p = (void*)(struct X { int i; } *)0;
// type name "struct X {int i;}*" used in the cast expression
// introduces the new type "struct X"
struct X x = {1}; // struct X is now in scopeСсылки
- Стандарт C23 (ISO/IEC 9899:2023):
- 6.2.5 Типы (стр.: TBD)
- 6.2.6 Представления типов (стр.: TBD)
- 6.2.7 Совместимые типы и составные типы (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
- 6.2.5 Типы (стр.: 31-33)
- 6.2.6 Представления типов (стр.: 31-35)
- 6.2.7 Совместимые типы и составные типы (стр.: 35-36)
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.2.5 Типы (стр.: 39-43)
- 6.2.6 Представления типов (стр.: 44-46)
- 6.2.7 Совместимые типы и составные типы (стр.: 47-48)
- Стандарт C99 (ISO/IEC 9899:1999):
- 6.2.5 Типы (стр.: 33-37)
- 6.2.6 Представления типов (стр.: 37-40)
- 6.2.7 Совместимые типы и составные типы (стр.: 40-41)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
- 3.1.2.5 Типы
- 3.1.2.6 Совместимые типы и составные типы
См. также
| Документация C++ для Типа |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/types