2015-11-26 4 views
1

test.hПоведение неинициализированного глобальной переменной в файле заголовка

#ifndef TEST_H 
#define TEST_H 

int i; 

int i = 1; // why no redefinition error issued? 

#endif /* TEST_H */ 

test.c

#include "test.h" 

int main() { 
    int x; 
    int x = i; // obviously, a redefinition 
    return 0; 
} 

Я действительно любопытно о поведении неинициализированного глобальной переменной файл заголовка. Насколько я знаю, оба «int i;» и «int i = 1» являются эффективными определениями для i, но на практике ни clang, ни gcc не выдают ошибку для этого случая. Может ли кто-нибудь объяснить детали?

+3

'int I;' это _declaration_ и _ ** предварительное ** определение_, а не «нормальное» _definition_. – Olaf

+0

Пахнет как неопределенное поведение. – Zimano

+0

Это похоже на описание, а не на объяснение. Если мы удалим конечный «int i = 1;» определение для i, каждый следующий доступ к i может видеть значение 0, которое автоматически назначается компилятором. Можете ли вы подробнее объяснить это подробно? Спасибо ~ – bagwell

ответ

1

Это предварительное определение, как описано here.

На верхнем уровне единицы перевода (то есть исходного файла со всеми #includes после препроцессора) каждая программа C представляет собой последовательность объявлений, которые объявляют функции и объекты с внешней связью. Эти объявления называются внешними объявлениями, потому что они появляются вне любой функции.

Предварительные определения

Предварительное определение является внешняя декларация без инициализатора, и либо без хранения класса спецификатор или с помощью спецификатора статической.

Предварительное определение - это декларация, которая может или не может выступать в качестве определения. Если фактическое внешнее определение найдено раньше или позже в той же самой системе перевода, то предварительное определение просто действует как декларация.

int i1 = 1;  // definition, external linkage 
int i1;   // tentative definition, acts as declaration because i1 is defined 
extern int i1; // declaration, refers to the earlier definition 

extern int i2 = 3; // definition, external linkage 
int i2;   // tentative definition, acts as declaration because i2 is defined 
extern int i2;  // declaration, refers to the external linkage definition 

Если нет определения в той же единице трансляции, то предварительное определение действует в качестве фактического определения с инициализатором = 0 (или, для типов массивов, = {0}).

int i3;  // tentative definition, external linkage 
int i3;  // tentative definition, external linkage 
extern int i3; // declaration, external linkage 
// in this translation unit, i3 is defined as if by "int i3 = 0;" 
+0

Спасибо за вашу ссылку! – bagwell

Смежные вопросы