为什么在.h文件中声明变量会为每个.c文件分配内存包括它,它是ANSI C吗?

时间:2013-06-14 07:29:54

标签: c compilation ansi

假设我有一个file.h并且我有:

int arr[128];
(void)(*func_ptr)(int);

我有code1.ccode2.ccode3.c包含它。 arrfunc_ptr将是为每个.c文件分配的全局范围吗?即每个.c文件都有自己的arrfunc_ptr实例?如果是这样,为什么会这样?

使用static可以改变结果吗?什么是ANSI c规则?

3 个答案:

答案 0 :(得分:4)

如果没有明确初始化变量,这些声明在C术语中称为“暂定定义”。您可以在多个编译单元中使用它们而不会出现问题。为了确保至少有一个符号有效实现的编译单元,你应该在一个单元中有一个真正的定义(包括初始化),比如

int arr[128] = { 0 };
(void)(*func_ptr)(int) = 0;

编辑:C标准的相关部分是6.9.2中的以下段落:

  

具有文件范围的对象的标识符声明   没有初始化程序,没有存储类说明符或没有   存储类说明符静态,构成一个暂定的   定义。如果翻译单元包含一个或多个暂定单元   标识符的定义,翻译单元包含否   该标识符的外部定义,然后行为是完全正确的   好像翻译单元包含一个文件范围声明   标识符,在翻译结束时使用复合类型   单位,初始化程序等于0。

答案 1 :(得分:2)

  

arr和func_ptr是否会为每个.c文件分配全局范围?

是的,最终会出现链接错误,因为您已在全局范围内为多个位置定义了相同的变量名称。

.c文件中#include的头文件只是插入到.c文件中,没有什么特别之处。它就像你连接.c文件包含的所有头文件一样,然后编译结果。

在这方面,最终结果就像你在每个.c文件中写了int arr[128];一样

答案 2 :(得分:1)

这不会编译,因为变量arr是全局范围,并且您将收到带有重复符号的链接器错误。

如果你声明它是静态的,那么它将在每个源文件中分配一个单独的内存,但是它只能在该源文件中或通过显式返回到不同文件的指针访问。

如果要访问每个源文件中的同一内存块,则必须在上面的一个文件中以及前面加extern的所有其他文件中声明它。

同样适用于func_ptr

<强>更新

如果将static添加到定义中,则无论您在何处定义,范围都是本地的。如果定义全局静态变量,它将仅在该模块中可见。如果在函数中定义静态变量,它将仅在该函数中可见,因此您可以在多个函数中使用相同的名称而不会产生干扰。

foo1()
{
     static int i;
}

foo2()
{
     static int i;
}

这样可以正常编译,因为它的行为类似于命名空间。