1

我使用一个 2D 字符数组,应该由 C 中的多个函数编写和读取。

这是我的数组:

static char array[3][6];

假设我有一个修改这个数组的函数'Function()'。如果函数在主文件中定义没有问题(数组被正确写入然后读取),但如果我想将我的函数放在另一个文件中,数组被正确写入但是当我在主文件中返回时神奇的空!这是我的代码。

主程序

#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;
}

支持.h

static char array[3][6];

支持.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 中的所有内容都可以,如果我分成两个文件它不会(数组从函数()返回后立即正确,然后它被释放),如何有可能吗?

4

3 回答 3

6

通过在头文件中声明array为静态,您可以为每个源文件提供包含support.h其自己的副本。您需要将标题更改为

extern char array[3][6];

并添加

char array[3][6];

到单个源文件。

于 2013-06-17T15:45:28.470 回答
4

声明文件级实体的全部意义static在于为其提供内部链接,即确保该实体对其他翻译单元不可见,并且每个翻译单元都有自己的此类实体的独立副本。这适用于函数和对象。在您的情况下,包含的每个翻译单元support.h都有自己独立的array对象副本。这正是您通过static在头文件中声明数组所实现的。这就是为什么main.c看不到任何修改的原因support.c——这两个翻译单元使用两个完全独立的数组。

现在,当我说数组从其他翻译单元“不可见”时,我的意思是您将无法从其他翻译单元按名称引用它(即您将无法链接到它)。这不一定是坏事。如果您仍想将数组声明为static并从其他翻译单元访问它,您仍然可以“手动”实现此访问:将该数组定义为static一个翻译单元,然后将该数组作为参数传递给所有其他函数。

(请注意,在大多数情况下,通过函数参数传递数组可能比引入全局变量更好。这甚至允许您将数组声明为本地对象main。)

但是如果你坚持使用真正的全局变量,你应该停止使用static. 根据@simonc 的答案在头文件中声明您的数组,并将其在其中一个翻译单元中定义为具有外部链接的对象。

于 2013-06-17T15:49:11.143 回答
2

好吧,实际上,array您在程序中定义了两个:一个在编译单元 main 中,另一个在编译单元支持中。编译器将一边编译 main.c,另一边编译 support.c,通常会创建目标文件(通常是 .obj 或 .o)。链接器将两者放在一起,解析地址。

因为您将数组定义为静态:

static char array[3][6];

你告诉编译器数组是编译单元私有的。并且因为 main.c 和 support.c 都包含 support.h,所以两者都在创建自己的 private array。main中的代码只能看到main.c中定义的数组,support.c中的代码只能看到support.c中定义的数组。当您调用 时Function(),即修改 support.c 中的数组,而不是 main.c 中可见的数组。

如果static从 support.h 中的定义中删除关键字array,则会出现链接器错误,因为该符号被定义了两次(在 main.c 和 support.c 中)。您必须决定在哪里定义数组(在 support.c 或 main.c 中)并使用extern关键字从其他源文件中引用它。

于 2013-06-17T15:55:09.820 回答