Initialization
Объявление объекта может предоставлять его начальное значение через процесс, известный как инициализация .
Для каждого декларатора инициализатор, если он не опущен, может быть одним из следующих:
=
выражение
|
(1) | ||||||||
=
{
список-инициализации
}
|
(2) | ||||||||
=
{
}
|
(3) | (начиная с C23) | |||||||
где initializer-list представляет собой непустой список, разделённый запятыми, из initializer ов (с необязательной завершающей запятой), где каждый инициализатор имеет одну из трёх возможных форм:
| выражение | (1) | ||||||||
{
список-инициализации
}
|
(2) | ||||||||
{
}
|
(3) | (начиная с C23) | |||||||
список-дескрипторов
=
инициализатор
|
(4) | (начиная с C99) | |||||||
|
где
designator-list
представляет собой список либо дескрипторов массива вида
Примечание: помимо инициализаторов, заключенный в фигурные скобки initializer-list может встречаться в составных литералах , которые являются выражениями вида:
|
(since C99) | ||||||||||||||||||||||||||||||||||||
Содержание |
Объяснение
Инициализатор определяет начальное значение, хранящееся в объекте.
Явная инициализация
Если предоставлен инициализатор, см.
- инициализация скалярных типов для инициализации скалярных типов
- инициализация массивов для инициализации массивов
- инициализация структур для инициализации структур и объединений.
Неявная инициализация
Если инициализатор не предоставлен:
- объекты с автоматической длительностью хранения инициализируются неопределёнными значениями (которые могут быть trap-представлениями )
- объекты со статической и thread-local длительностью хранения подвергаются пустой инициализации
Пустая инициализация
|
Объект является пусто-инициализированным, если он явно инициализирован из инициализатора = { } . |
(начиная с C23) |
В некоторых случаях объект инициализируется пустым значением, если он не инициализирован явно, то есть:
- указатели инициализируются нулевыми значениями указателей их типов
- объекты целочисленных типов инициализируются беззнаковым нулём
- объекты типов с плавающей запятой инициализируются положительным нулём
- все элементы массивов, все члены структур и первые члены объединений рекурсивно инициализируются пустыми значениями, плюс все биты заполнения инициализируются нулями
- (на платформах, где нулевые значения указателей и нули с плавающей запятой имеют представление в виде всех нулевых битов, эта форма инициализации статических переменных обычно реализуется путем их размещения в секции .bss образа программы)
Примечания
При инициализации объекта со статической или поточной длительностью хранения , каждое выражение в инициализаторе должно быть константным выражением или строковым литералом .
Инициализаторы нельзя использовать в объявлениях объектов неполного типа, VLA и объектов с областью видимости блока, имеющих линковку.
Начальные значения параметров функции устанавливаются как бы присваиванием из аргументов вызова функции , а не инициализацией.
Если неопределённое значение используется в качестве аргумента для любого вызова стандартной библиотеки, поведение не определено. В противном случае результат любого выражения с неопределёнными значениями является неопределённым значением (например, int n ; , n может не быть равным самому себе и может казаться, что его значение меняется при последующих чтениях)
|
В языке C нет специальной конструкции, соответствующей value initialization в C++; однако, = { 0 } (или ( T ) { 0 } в составных литералах) (since C99) может использоваться вместо этого, поскольку стандарт C не допускает пустых структур, пустых объединений или массивов нулевой длины. |
(until C23) |
|
Пустой инициализатор = { } (или ( T ) { } в составных литералах) может использоваться для достижения той же семантики, что и value initialization в C++. |
(since C23) |
Пример
#include <stdlib.h> int a[2]; // инициализирует a в {0, 0} int main(void) { int i; // инициализирует i в неопределенное значение static int j; // инициализирует j в 0 int k = 1; // инициализирует k в 1 // инициализирует int x[3] в 1,3,5 // инициализирует int* p в &x[0] int x[] = { 1, 3, 5 }, *p = x; // инициализирует w (массив из двух структур) в // { { {1,0,0}, 0}, { {2,0,0}, 0} } struct {int a[3], b;} w[] = {[0].a = {1}, [1].a[0] = 2}; // выражение вызова функции может быть использовано для локальной переменной char* ptr = malloc(10); free(ptr); // Ошибка: объекты со статической продолжительностью хранения требуют константных инициализаторов // static char* ptr = malloc(10); // Ошибка: VLA не может быть инициализирован // int vla[n] = {0}; }
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.7.9 Инициализация (стр. 100-105)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.7.9 Инициализация (стр: 139-144)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 6.7.8 Инициализация (стр: 125-130)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 6.5.7 Инициализация
Смотрите также
|
C++ documentation
для
Initialization
|
`, `
`, `