void main()
{
extern int i;
printf("%d\n",i);
}
int i;//definetion
int i=35;//definition
在上面的代码中,int i
表示i=0;
,int i=35
表示i=35
。
那么为什么编译器没有给出redefinition
的错误?
答案 0 :(得分:3)
在ansi标准中,他们称int x;
为“暂定”定义。
这就是ansi标准所说的:
具有文件范围的对象的标识符声明 没有初始化程序,没有存储类说明符或没有 存储类说明符静态,构成一个暂定的 定义。如果翻译单元包含一个或多个暂定单元 标识符的定义,翻译单元包含否 该标识符的外部定义,然后行为是完全正确的 好像翻译单元包含一个文件范围声明 标识符,在翻译结束时使用复合类型 单位,初始化程序等于0。
举例:
int i1 = 1; /* definition, external linkage */
static int i2 = 2; /* definition, internal linkage */
extern int i3 = 3; /* definition, external linkage */
int i4; /* tentative definition, external linkage */
static int i5; /* tentative definition, internal linkage */
int i1; /* valid tentative definition, refers to previous */
int i2; /* $3.1.2.2 renders undefined, linkage disagreement */
int i3; /* valid tentative definition, refers to previous */
int i4; /* valid tentative definition, refers to previous */
int i5; /* $3.1.2.2 renders undefined, linkage disagreement */
extern int i1; /* refers to previous, whose linkage is external */
extern int i2; /* refers to previous, whose linkage is internal */
extern int i3; /* refers to previous, whose linkage is external */
extern int i4; /* refers to previous, whose linkage is external */
extern int i5; /* refers to previous, whose linkage is internal */
在我的理解,只要你想,最多一个定义(与初始化),你可以有相同的对象尽可能多的初步定义。如果没有定义,暂定定义将转换为定义,并在文件末尾使用initializer == 0。
换句话说,打印的值是35,因为有一个初始化程序。
答案 1 :(得分:1)
从6.7.5开始:
“标识符的定义是该标识符的声明: - 对于一个对象,导致为该对象保留存储; ......“
所以int i;
和int i = 35;
都是定义(也是声明,因为所有定义都是声明)。
不同之处在于int i = 35;
也有一个显式初始化器,而int i;
只有在没有外部定义的情况下才会隐式初始化为0(假设全局因此是静态存储持续时间):
来自6.2.9.2:
具有没有初始化程序的文件范围的对象的标识符声明,以及 没有存储类说明符或存储类说明符静态,构成一个 暂定的定义。如果翻译单元包含一个或多个临时定义 然后,标识符和转换单元不包含该标识符的外部定义 行为就像翻译单元包含该文件范围声明一样 标识符,具有复制类型,如翻译单元的末尾,带有初始化程序 等于0。
请注意,这些暂定定义在c ++中不可用。 (见附录C1.2第3.1条)
因此,在这种情况下,将打印值35
,因为这是i
初始化的值。