Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在.h文件中声明变量会为每个包含它的.c文件分配内存,是ANSI c吗?_C_Compilation_Ansi - Fatal编程技术网

为什么在.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术语中称为“暂定定义”。您可以在多个编译单元中毫无问题地使用它们。为了确保至少有一个编译单元有效地实现了符号,您应该在其中一个单元中有一个真正的定义(包括初始化),例如

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