Инициализация глобальной и статической переменных в 0 всегда не нужна?
Стандарт C гарантирует, что глобальные и статические переменные, если они не инициализированы, всегда 0
.
Здесь мой вопрос: неинициализированные глобальные и статические переменные переходят в сегмент BSS
в программе. Итак, так называемый 0
должен быть all-bit 0
.
Для интегральных переменных all-bit 0
будет оцениваться как 0
. Переменные с плавающей запятой, если следующий IEEE 754, также 0.0
. Но для указателей нулевые указатели необязательно должны быть all-bit 0
, поэтому инициализация глобального указателя выглядит так:
int* p = NULL;
имеет значение только:
int *p;
Ответы
Ответ 1
Стандарт гарантирует, что указатель со статической продолжительностью хранения и никакой другой инициализатор будет инициализирован как нулевой указатель, независимо от того, какой бит-шаблон может включать.
Эта же основная идея относится и к типам с плавающей запятой и целыми числами - они также могут быть инициализированы до 0 или 0,0. Реализация может оставить это в том, что BSS устанавливает все биты в 0 тогда и только тогда, когда "знает", что это приведет к правильным значениям.
Ответ 2
Все переменные со статической продолжительностью хранения гарантированно инициализируются до их нулевых значений, что обычно не означает, что они должны быть физически заполнены шаблоном с нулевым числом.
Причина, по которой такие переменные могут перейти в сегмент BSS на определенной платформе, такова, что на целевой платформе нулевой указатель действительно представлен шаблоном с полным битом. То есть инициализация all-bits-zero для указателей просто работает правильно на этой платформе, поэтому компилятор использует BSS как самый простой и эффективный способ реализации правильного поведения на этой конкретной платформе. Если это не так, компилятору придется инициализировать такие статические переменные по-разному.
Это применимо к значениям с плавающей запятой, например, если на какой-либо платформе используется представление, отличное от IEEE 754, для таких значений с ненулевым битовым шаблоном для представления 0.0
(C не имеет мандата IEEE 754).
(Более того, это даже использовалось для всех интегральных типов, больших, чем char
, пока один из TC для стандарта C99 окончательно не потребовал, чтобы шаблон all-bits-zero был допустимым представлением объекта для целых нулей всех типов на все платформы C.)
Хороший пример из реальной жизни исходит из С++ (в данном случае это другой язык, но актуальный). С++ обеспечивает ту же гарантию для скалярных переменных со статической продолжительностью хранения. Между тем, во многих популярных реализациях С++ используется значение 0xFFFFFFFF
для представления нулевых указателей типа типа указателя на данные. Например.
SomeType SomeClass::*p = 0;
фактически преобразуется в код, который заполняет p
шаблоном all-bits-one. Таким образом, если вы объявляете статическую переменную такого типа без явного инициализатора, компилятор должен будет убедиться, что его начальное значение является шаблоном "все-бит-один", а не паттерном "all-bits-zero". Некоторые компиляторы, как известно, ошибаются, помещая такие переменные в BSS, забывают о них, оставляя таким образом переменные, заполненные шаблоном с нулевым числом.