为什么在.h文件中声明变量会为每个包含它的.c文件分配内存,是ANSI c吗?
假设我有一个为什么在.h文件中声明变量会为每个包含它的.c文件分配内存,是ANSI c吗?,c,compilation,ansi,C,Compilation,Ansi,假设我有一个文件.h,其中有: int arr[128]; (void)(*func_ptr)(int); 我有code1.c,code2.c,code3.c包括它。arr和func\u ptr是否将为每个.c文件分配全局作用域?i、 e.每个.c文件都有自己的arr和func_ptr实例?如果是,为什么 使用static是否会改变结果?ANSI c规则是什么?这将不会编译,因为变量arr是一个全局范围,您将得到一个带有重复符号的链接器错误 如果将其声明为静态,则会在每个源文件中分配一个单独的
文件.h
,其中有:
int arr[128];
(void)(*func_ptr)(int);
我有code1.c
,code2.c
,code3.c
包括它。arr
和func\u ptr
是否将为每个.c文件分配全局作用域?i、 e.每个.c文件都有自己的arr
和func_ptr
实例?如果是,为什么
使用
static
是否会改变结果?ANSI c规则是什么?这将不会编译,因为变量arr
是一个全局范围,您将得到一个带有重复符号的链接器错误
如果将其声明为静态,则会在每个源文件中分配一个单独的内存,但只能在该源文件中或通过显式返回到不同文件的指针访问
如果要访问每个源文件中的同一内存块,则必须在一个文件中声明它,如上所述,并在所有其他文件中声明extern
前缀
func_ptr
更新
如果将static
添加到定义中,则无论您在何处定义,范围都是本地的。如果您定义了一个全局静态变量,它将仅在该模块中可见。如果在函数中定义静态变量,它将仅在该函数中可见,因此可以在多个函数中使用相同的名称,而不会产生干扰
foo1()
{
static int i;
}
foo2()
{
static int i;
}
这可以很好地编译,因为它的行为类似于命名空间。这不会编译,因为变量
arr
是一个全局范围,您将得到一个带有重复符号的链接器错误
如果将其声明为静态,则会在每个源文件中分配一个单独的内存,但只能在该源文件中或通过显式返回到不同文件的指针访问
如果要访问每个源文件中的同一内存块,则必须在一个文件中声明它,如上所述,并在所有其他文件中声明extern
前缀
func_ptr
更新
如果将static
添加到定义中,则无论您在何处定义,范围都是本地的。如果您定义了一个全局静态变量,它将仅在该模块中可见。如果在函数中定义静态变量,它将仅在该函数中可见,因此可以在多个函数中使用相同的名称,而不会产生干扰
foo1()
{
static int i;
}
foo2()
{
static int i;
}
这将很好地编译,因为它的行为类似于名称空间
arr和func_ptr是否将为每个.c文件分配全局作用域
是的,它会,并且您将以链接错误结束,因为您已经在全局范围的多个地方定义了相同的变量名
包含在.c文件中的头文件只是插入到.c文件中,没有什么特别之处。它的工作原理与连接.c文件包含的所有头文件一样,然后编译结果
在这方面,最终结果与您编写的intarr[128]完全相同代码>在每个.c文件中
arr和func_ptr是否将为每个.c文件分配全局作用域
是的,它会,并且您将以链接错误结束,因为您已经在全局范围的多个地方定义了相同的变量名
包含在.c文件中的头文件只是插入到.c文件中,没有什么特别之处。它的工作原理与连接.c文件包含的所有头文件一样,然后编译结果
在这方面,最终结果与您编写的intarr[128]完全相同在每个.c文件中的代码>声明中,这些没有显式初始化变量的声明在c术语中称为“暂定定义”。您可以在多个编译单元中毫无问题地使用它们。为了确保至少有一个编译单元有效地实现了符号,您应该在其中一个单元中有一个真正的定义(包括初始化),例如
int arr[128] = { 0 };
(void)(*func_ptr)(int) = 0;
编辑:C标准的相关部分见6.9.2的以下段落:
具有文件作用域的对象的标识符声明
没有初始值设定项,也没有存储类说明符或
存储类说明符static构成了一个
释义如果翻译单元包含一个或多个暂定
标识符的定义,并且翻译单元不包含
该标识符的外部定义,则该行为
就好像翻译单元包含一个文件范围声明一样
标识符,具有转换结束时的复合类型
单位,初始值设定项等于0
在C行话中,这些没有显式初始化变量的声明称为“暂定定义”。您可以在多个编译单元中毫无问题地使用它们。为了确保至少有一个编译单元有效地实现了符号,您应该在其中一个单元中有一个真正的定义(包括初始化),例如
int arr[128] = { 0 };
(void)(*func_ptr)(int) = 0;
编辑:C标准的相关部分见6.9.2的以下段落:
具有文件作用域的对象的标识符声明
没有初始值设定项,也没有存储类说明符或
存储类说明符static构成了一个
释义如果翻译单元包含一个或多个暂定
标识符的定义,并且翻译单元不包含
该标识符的外部定义,则该行为
就好像翻译单元包含一个文件范围声明一样
标识符,具有转换结束时的复合类型
单位,初始值设定项等于0
检查一下,OP是否在头文件中声明了它,并且只定义了onc