C语言中多个文件中的静态二维数组
我使用一个2D字符数组,该数组应该由C中的多个函数写入和读取 这是我的阵列:C语言中多个文件中的静态二维数组,c,arrays,static,header,C,Arrays,Static,Header,我使用一个2D字符数组,该数组应该由C中的多个函数写入和读取 这是我的阵列: static char array[3][6]; 假设我有一个函数“function()”修改这个数组。 如果函数是在main中定义的,则没有问题(数组是正确写入的,然后是读取的),但是如果我想在另一个文件中使用我的函数,则数组是正确写入的,但是当我返回main时,数组会神奇地变空! 这是我的密码 main.c #include "support.h" int main(int argc, char *argv[]
static char array[3][6];
假设我有一个函数“function()”修改这个数组。
如果函数是在main中定义的,则没有问题(数组是正确写入的,然后是读取的),但是如果我想在另一个文件中使用我的函数,则数组是正确写入的,但是当我返回main时,数组会神奇地变空!
这是我的密码
main.c
#include "support.h"
int main(int argc, char *argv[])
{
Function();
unsigned i, j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 6; j++)
printf("[%c]", array[i][j]);
printf("\n");
}
system("PAUSE");
return 0;
}
支持.c
void Function()
{
char hello[6];
hello[0] = 'H';
hello[1] = 'E';
hello[2] = 'L';
hello[3] = 'L';
hello[4] = 'O';
hello[5] = '\0';
strcpy(array[0], hello);
}
没有编译错误或运行时错误。再一次,如果我尝试将main.c中的所有内容都移动,如果我将它们分成两个不工作的文件(数组从函数()返回时是正确的,那么它就被释放了),这怎么可能呢?通过在头文件中将
array
声明为static,可以为每个包含support.h
的源文件提供自己的副本。您需要将标题更改为
extern char array[3][6];
加
char array[3][6];
到单个源文件。通过在头文件中将
数组
声明为静态,可以为包含support.h的每个源文件提供自己的副本。您需要将标题更改为
extern char array[3][6];
加
char array[3][6];
到单个源文件。声明文件级实体静态
的全部目的是为其提供内部链接,即确保该实体对其他翻译单元不可见,并且每个翻译单元都有自己的独立副本。这适用于函数和对象。在您的例子中,包含support.h
的每个翻译单元都有自己的数组
对象的独立副本。这正是通过在头文件中声明静态
数组实现的。这就是为什么main.c
无法在support.c
中看到任何修改的原因-这两个翻译单元使用两个完全独立的数组
现在,当我说数组在其他翻译单元中“不可见”时,我的意思是,您将无法从其他翻译单元按名称引用它(即,您将无法链接到它)。这不一定是坏事。如果您仍然希望将数组声明为静态
,并从其他翻译单元访问它,您仍然可以“手动”实现此访问:在一个翻译单元中将该数组定义为静态
,然后将该数组作为参数传递给所有其他函数
(注意,在大多数情况下,通过函数参数传递数组可能比引入全局变量要好得多。这甚至允许您在main
中将数组声明为本地对象)
但如果坚持使用真正的全局变量,则应停止使用静态变量。根据@simonc answer在头文件中声明您的arrray,并在其中一个翻译单元中将其定义为具有外部链接的对象。声明文件级实体静态
的关键在于为其提供内部链接,也就是说,确保该实体对其他翻译单位不可见,并且每个翻译单位拥有该实体的独立副本。这适用于函数和对象。在您的例子中,包含support.h
的每个翻译单元都有自己的数组
对象的独立副本。这正是通过在头文件中声明静态
数组实现的。这就是为什么main.c
无法在support.c
中看到任何修改的原因-这两个翻译单元使用两个完全独立的数组
现在,当我说数组在其他翻译单元中“不可见”时,我的意思是,您将无法从其他翻译单元按名称引用它(即,您将无法链接到它)。这不一定是坏事。如果您仍然希望将数组声明为静态
,并从其他翻译单元访问它,您仍然可以“手动”实现此访问:在一个翻译单元中将该数组定义为静态
,然后将该数组作为参数传递给所有其他函数
(注意,在大多数情况下,通过函数参数传递数组可能比引入全局变量要好得多。这甚至允许您在main
中将数组声明为本地对象)
但如果坚持使用真正的全局变量,则应停止使用静态变量。根据@simonc answer在头文件中声明您的数组,并在其中一个翻译单元中将其定义为具有外部链接的对象。实际上,您的程序中定义了两个array
:一个在编译单元main中,另一个在编译单元支持中。编译器将一边编译main.c,另一边支持.c,通常创建对象文件(通常是.obj或.o)。链接器将两者放在一起,解析地址
因为您将数组定义为静态:
static char array[3][6];
您告诉编译器数组是编译单元的私有数组。因为main.c和support.c都包含support.h,所以它们都在创建自己的私有数组。main中的代码只能看到main.c中定义的数组,support.c中的代码只能看到support.c中定义的数组。调用函数()
时,这是在修改support.c中的数组,而不是main.c中可见的数组
如果从support.h中的数组
定义中删除static
关键字,则会出现链接器错误,因为该符号定义了两次(在main.c和support.c中)。您必须决定要在何处定义数组(在support.c或main.c中),并使用extern
关键字从其他源文件中引用它。实际上,您的程序中定义了两个array
:一个在编译单元main中,另一个在编译单元支持中。编译器将