我写了以下程序
#include<stdio.h>
main ()
{
extern int i;
printf("\n%d",i);
}
int i=30;
我期待一条错误消息,因为我在main之后被初始化,但相反程序给了我输出。为什么它没有给我一个错误是我想知道的。
答案 0 :(得分:21)
extern
的全部目的是它说“在项目的某个地方有一个名为int
的{{1}}类型的变量,可能会在以后链接。只是假设它存在”。
您可以在一个完全独立的i
文件中定义i
,只要您将.c
个文件链接在一起,它仍然有用。 这就是.o
所做的。
就像你如何声明一个函数并使用它一样,即使它是在一个完全独立的extern
文件中定义的(或者,实际上,稍后在同一个文件中)。
阅读C书中有关.c
。
答案 1 :(得分:8)
因为代表i的符号仍然存在于程序空间中。通过声明它是“extern”,你告诉编译器在遇到它之前不一定要期望“i”的定义......换句话说,你明确告诉编译器要相信该符号将在以后链接
从根本上说,这与在完全独立的库中具有函数定义并在主函数中声明它是extern没有任何不同。订单不重要,因为符号仍然会被链接。
答案 2 :(得分:3)
extern是在当前模块外部定义的东西。您可以使用extern,以防您的声明稍后,或者甚至当您的声明在其他文件中时,尚未遇到。
[节省你的努力 - &gt;下面的行是FROM WIKIPEDIA]
定义变量时,您告诉编译器为该变量分配内存,并且可能还要将其内容初始化为某个值。
当你声明一个变量时,你告诉编译器变量是在别处定义的。
您只是告诉编译器存在一个由该名称和类型组成的变量,但编译器不应该为它分配内存,因为它是在其他地方完成的。
extern关键字表示“声明而不定义”。换句话说,它是一种显式声明变量或强制声明而无需定义的方法。
了解详情:http://wiki.answers.com/Q/What_is_the_use_of_extern_in_C#ixzz1OzrWVmAC
答案 3 :(得分:3)
如果您想更深入地了解如何从main访问i以及何时初始化i,您可以查看示例程序集输出。如下面的评论所述,它来自一个工具链(gcc / linux),但应该有助于给出一个好的图片。它显示我在数据段中,并在执行main之前初始化。
.file "test.c"
.section .rodata
.LC0:
.string "\n%d"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl i, %edx
movl $.LC0, %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
leave
ret
.size main, .-main
.globl i
.data
.align 4
.type i, @object
.size i, 4
i:
.long 30
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits
答案 4 :(得分:1)
因为我在主b
之后被初始化,所以我期待一条错误消息
全局变量(因为具有静态存储持续时间的所有变量)在main()中的代码开始执行之前被初始化,而不管您在其中定义它们的位置。