为什么以下计划有效

时间:2011-06-11 19:16:11

标签: c extern

我写了以下程序

#include<stdio.h>
 main ()
{
        extern int i;
        printf("\n%d",i);
}
int i=30;

我期待一条错误消息,因为我在main之后被初始化,但相反程序给了我输出。为什么它没有给我一个错误是我想知道的。

5 个答案:

答案 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()中的代码开始执行之前被初始化,而不管您在其中定义它们的位置。