假设我有一个file.h
并且我有:
int arr[128];
(void)(*func_ptr)(int);
我有code1.c
,code2.c
,code3.c
包含它。 arr
和func_ptr
将是为每个.c文件分配的全局范围吗?即每个.c文件都有自己的arr
和func_ptr
实例?如果是这样,为什么会这样?
使用static
可以改变结果吗?什么是ANSI c规则?
答案 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;
}
这样可以正常编译,因为它的行为类似于命名空间。