2016-10-16 12 views
2

Почему этот код разрешен в C?Переопределение глобальных переменных, разрешенных в C?

int x; 

int main() { 
    printf("%d\n", x); 
    return 0; 
} 

int x = 2; 

Он компилируется без предупреждений с помощью -Wall -std=c89 как с gcc и clang.

Ранее я считал, что int x при глобальном масштабе эквивалентен int x = 0. Я удивляюсь.

+0

@ pablo1977 'x' ** является ** статической переменной! – Olaf

ответ

1

int x;, в области видимости файла, является предварительного определения и ответил @PSkocik и будет действовать как int x = 0; если определение с инициализацией не существует.

Я раньше считал, что int x в глобальном масштабе эквивалентен int x = 0.

Хитрости о «глобальном» int x; приобретает инициализируются с 0. инициализируются 0, если другой int x = constant; не существует в любом модуле компиляции.

Поэтому рекомендуется инициализировать явную инициализацию и не рассчитывать на инициализацию по умолчанию на 0 бит, когда объект нуждается в инициализации.

// Does an initialization exist, in some file -maybe? 
int x; 
// Better. If another file initializes `x`, good to see a compiler/linker error. 
int x = 0; 
+0

Я не думаю, что это совершенно правильно. Имея одно предварительное определение в одном ТУ и одно с инициализатором в другом, не покрывается стандартом. Это два противоречивых определения и, таким образом, приводят к UB. Однако gcc делает это как расширение, но другие компиляторы не могут. –

+0

@JensGustedt Возможно так. Пересмотрит. – chux

-2
int x; 

Является декларацией.

int x = 2; 

Это определение (которое также является декларацией).

Повторное объявление разрешено до тех пор, пока декларации совместимы (то же самое).

int x; 
int x; 

Будет работать. Повторное определение не допускается

int x = 2; 
int x = 2; 

Не сработает.
Использование без объявления перед ним или без определения отвергается

+2

'int x;' в области файлов - это определение _tentative_. И 'int x = 2;' также является объявлением. – Olaf

+0

@ Олаф, да, но пока существует реальное определение, предварительные определения не имеют значения. Как говорится в названии, это условно, пока никто другой не приходит. –

+0

И имена с внешней связью должны всегда иметь декларацию 'extern', лучше всего в файле заголовка. В противном случае используйте внутреннюю связь. – Olaf