1

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

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

我有code1.c, code2.c,code3.c包括它。是否将为每个 .c 文件分配全局范围arrfunc_ptr即每个 .c 文件都有自己的arrand实例func_ptr?如果是这样,那是为什么?

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

4

3 回答 3

4

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

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

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

具有文件范围的对象的标识符声明没有初始化程序,并且没有存储类说明符或具有存储类说明符 static,构成暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则行为与翻译单元包含该标识符的文件范围声明完全相同,复合类型为翻译单元的末尾,初始化器等于 0。

于 2013-06-14T07:45:39.387 回答
2

arr 和 func_ptr 将是为每个 .c 文件分配的全局范围吗?

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

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

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

于 2013-06-14T07:33:27.593 回答
1

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

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

如果要访问每个源文件中的同一块内存,则必须如上所述在一个文件中声明它,并在所有其他文件中声明它extern

同样适用于func_ptr

更新

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

foo1()
{
     static int i;
}

foo2()
{
     static int i;
}

这可以很好地编译,因为它的行为类似于命名空间。

于 2013-06-14T07:32:16.760 回答