Любое определение объекта может включать значение или список значений для его
инициализации, в этом случае за декларацией следует знак равенства
(=
) и начальное значение(я).
Начальное значение объекта со статической продолжительностью хранения может быть любым выражением, которое вычисляется в константное значение, включая использование оператора взятия адреса функции или объекта со статической продолжительностью хранения.
Начальное значение объекта с автоматической продолжительностью хранения может быть любым выражением, которое можно присвоить этому объекту, включая ссылки на другие объекты. Вычисление начальных значений происходит в том же порядке, что и определения объектов.
Начальное значение для скалярного типа (указатели, целые и типы с плавающей точкой) могут быть заключены в фигурные скобки, хотя те и не являются обязательными.
Следующие декларации допустимы внутри функции:
static int MaxRecLen = 1000; static int MaxMemSize = { 1000 * 8 + 10000 }; float Pi = 3.14159; auto int x = 3; register int y = x * MaxRecLen;
Для массивов символов, которые инициализируются стринговым литералом, и для
массивов wchar_t
, которые инициализируются расширенным
стринговым литералом, фигурные скобки, окружающие начальные значения
необязательны. Для других массивов — обязательны.
Если инициализируется массив неопределённого размера, то его размер определяется числом инициализирующих значений. В частности, массив символов неизвестного размера может быть инициализирован стринговым литералом и в этом случае размер массива будет равен числу символов в стринге плюс закрывающий нулевой символ. Каждый символ стринга помещается в последовательные элементы массива. Рассмотрим следующие декларации:
char StartPt[] = "Starting point..."; int Tabs[] = { 1, 9, 17, 25, 33, 41 }; float Roots[] = { 1., 1.414, 1.732, 2., 2.236 };
Объект StartPt
является массивом из 18 символов,
Tabs
— массив 6 целых, а Roots
— массив
из 5 чисел с плавающей точкой.
Если декларирован массив с определённым числом элементов, то максимальное число значение в списке инициализаторов — число элементов массива. Исключение сделано для массивов символов, где инициализатором может быть стринг той же длины, что и число символов в массиве. Каждый символ из стринга присваивается соответствующему элементу массива. Нулевой символ в конце стрингового литерала игнорируется.
Если инициализирующих значений меньше числа элементов массива, то оставшимся элементам, не получившим значение, присваивается нуль (для арифметических типов) или константа null-указатель (для указателей). Рассмотрим следующие примеры:
char Vowels1[6] = "aeiouy"; char Vowels2[6] = { 'a', 'e', 'i', 'o', 'u', 'y' }; int Numbers[10] = { 100, 10, 1 }; float Blort[5] = { 5.6, -2.2 };
Объекты Vowels1
и Vowels2
— массивы из шести
символов, и оба содержат одинаковые значения в соответствующих элементах.
Объект Numbers
— массив из 10
целых, первым
трём из которых присвоены значения 100
, 10
и
1
, а оставшиеся установлены в нуль. Объект Blort
— массив из 5
чисел с плавающей точкой. Первые два
инициализированы значениями 5.6
и -2.2
, а
оставшиеся три равны нулю.
Если инициализируется массив большей размерности, чем единица, то каждый подмассив может инициализироваться списком значений заключённым в фигурные скобки. Этот способ будет работать для любой размерности. Рассмотрим случай двумерного массива:
int Box[3][4] = { { 11, 12, 13, 14 }, { 21, 22, 23, 24 }, { 31, 32, 33, 34 } };
Объект Box
является массивом из 3
массивов по
4
целых. В списке инициализации — три значения,
соответствующих первому измерению (3
строки). Каждое из них
— список значений соответствующих второму (4
колонки).
Другими словами, первый список значений, { 11, 12, 13, 14 }
,
присваивается первой строке переменной Box
, второй, { 21,
22, 23, 24 }
, — второй строке, а третий, { 31, 32, 33, 34
}
, — третьей.
Если в список входят все значения для инициализации массива или не включаются
элементы только в конце массива, то подуровни в фигурные скобки можно не
заключать. Например, следующая декларация объекта Box
такая же,
как предыдущая:
int Box[3][4] = { 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34 };
Правила, касающиеся неполного списка инициализаторов, применимы и для многомерных массивов. Следующий пример определяет математическую единичную матрицу 3 на 3:
int Identity[3][3] = { { 1 }, { 0, 1 }, { 0, 0, 1 } };
Пропущенные значения будут заменены нулями. Инициализацию можно сделать и так:
int Identity[3][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
или так:
int Identity[3][3] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
Структуры инициализируются похожим на массивы образом. Список инициализаторов должен быть заключён в фигурные скобки.
Например,
struct printformat { int pagewid; char carr_ctl; char * buffer; }; char PrBuffer[256]; struct printformat PrtFmt = { 80, ' ', PrBuffer };
Каждое значение из списка инициализаторов присваивается последующему члену структуры. Любые неименованные промежутки между членами или в конце структуры (вызванные выравниванием) игнорируются во время инициализации. Если в структуре больше членов, чем указано значений в списке инициализаторов, то оставшимся членам присваивается нуль (для арифметических членов) либо константа null-указатель (для указателей).
Если член структуры сам является массивом, структурой или объединением, то его члены могут быть инициализированы с использованием списка инициализаторов заключённого в фигурные скобки. Если фигурные скобки отсутствуют, то для инициализации подчлены трактуются как члены внешней структуры, так, что каждое последующее значение инициализирует очередной подчлен пока они есть, затем инициализируется следующий член внешней структуры.
Инициализация объединений производится также, как и инициализация структур, за исключением того, что инициализировать можно только первый член, используя инициализатор, заключённый в фигурные скобки.
Рассмотрим следующий пример:
struct first3 { char first, second, third; }; union ustr { char string[20]; struct first3 firstthree; }; union ustr Str = { "Hello there" };
Объект Str
декларирован как объединение двух типов, первый из
которых — массив из 20 символов, а второй — структура,
предоставляющая прямой доступ к первым трём символам содержащимся в массиве.
Массив инициализирован стрингом "Hello there"
. Три символа в
struct first3
будут содержать символы 'H'
,
'e'
и 'l'
. Если же ustr
декларировать
как:
union ustr { struct first3 firstthree; char string[20]; };
то инициализировать можно будет только первые три символа.
Объект со статической продолжительностью хранения без явно заданной инициализации будет инициализирован как, если бы всем членам арифметического типа был присвоен нуль, а членам, которые имеют тип указателя, был присвоен null-указатель (нуль).
Объект с автоматической продолжительностью хранения при отсутствии явной инициализации не инициализируется. Поэтому ссылка на автоматические объекты, которым не присвоено какое-либо значение приведёт к неопределённому поведению. На большинстве систем значение объекта будет случайным и непредсказуемым.