8

根据我对全局变量和静态变量的了解,如果 C 变量在源文件中的所有函数之外声明为:

int a;  

一旦该变量在该文件中有一个 extern 声明,其他文件就可以访问该变量。
但是如果相同的变量被声明为:

static int a;

那么这个变量只能被当前文件使用,任何其他文件都看不到这个变量。

  1. 当程序在运行时加载到内存中时,全局变量和静态变量都存在于该程序的数据部分中。
    我想了解,由于两者都存储在同一个内存段中,如何保护静态变量不被用于超出其范围的任何指令。
    我认为变量的范围及其访问将由编译器处理。如果我错了,请发表评论,如果我遗漏任何细节,请添加。

  2. 关于外部变量。如果,

    int a;  
    

    在文件 file1.c 中定义并在文件 file2.c 中声明为:

    extern int a;  
    

    这两个文件属于不同的进程,分别是 process1 和 process2。因此,当 process1 正在运行并且它的地址空间被加载到内存中时,它的数据段变量“a”将可用。
    我这里有个疑问,就是process2运行的时候,这个变量会不会也加载到process2的data段呢?或如何管理。

请帮助我清除我上面提到的疑虑。我在网上搜索并阅读了几篇文章,需要确认我是否理解正确。
Aso,请给我推荐一篇好的文章或书籍,这将有助于我清楚地理解上述概念。

4

5 回答 5

12

首先,正如您所说,不同的进程具有不同的地址空间。因此,除非您明确共享它们(共享内存等),否则它们不会共享任何内存。

关于全局静态变量与全局非静态变量,区别称为链接:非静态全局变量具有外部链接,这意味着它们具有链接器的名称,因此一个编译单元(.c 文件)可以访问变量定义在另一个。

然而,静态全局变量具有内部链接,因此,尽管它可能与前者位于同一内存块中,但它没有链接器的名称,因此除了它自己的编译单元之外,它不能在任何其他编译单元中使用。

于 2013-06-06T07:38:49.827 回答
2
  1. 静态变量在内存中被分配了一个地址和一个大小,但它们不会被广告。因此,如果我static int a;在一个文件中有一个文件并尝试extern int a;从另一个文件中引用它,则找不到“链接端”,因此它不起作用。

    为了extern工作,必须有“某事”来宣传a可用,什么static不可用。

  2. 不,它们不属于不同的进程。它们被链接到一个可执行文件中,然后执行。不同的进程通常不能访问彼此的内存。

于 2013-06-06T07:36:42.943 回答
1

在文件范围内有一个static变量使得它在链接时对链接器不可见。编译器不会发出一个符号(对应于变量命名)应该对链接器可见的指令。

关于第二个问题,extern int a只是一个声明。它不为该变量保留任何空间,而只是通知编译器该变量存在于某处。稍后链接该单元时,链接器会解析对该变量的引用。

于 2013-06-06T07:36:34.823 回答
1

1 我认为变量的范围及其访问将由编译器处理。如果我错了,请发表评论,如果我遗漏任何细节,请添加。

那是对的。C 编译器不会使其他编译单元可以访问此变量,因此您无法成功编译直接访问该变量的程序。C 将此概念称为链接

您可以编写一个非静态函数来返回其地址以间接访问它:

static int a;

int *get_a(void)
{ 
  return &a;
}

a现在其他编译单元可以通过调用间接访问get_a()

除此之外,这取决于特定的编译器在运行时如何表示。如果你能以某种方式在 C 之外找出 的位置a,你可以随心所欲地处理它。通常没有特殊保护之类的。

2 关于外部变量。如果 process2 运行时,这个变量是否也会加载到 process2 的数据部分?或如何管理。

普通的 destktop/server 操作系统为每个进程提供虚拟内存。在内存方面,这些进程彼此独立,并且 process2 看到它自己的变量副本,这与process1 中a的副本没有任何关系。a唯一的共同点是它们是从同一个可执行文件加载的。

于 2013-06-06T13:06:42.470 回答
0

both files belongs to different processes意味着编译器对所指的内容绝对没有参考extern int a;。它不会搜索您计算机上的每一段代码并希望它找到一个且只有一个int a;声明,然后添加一堆编程来检测和访问该进程的内存。除了是可怕的行为之外,复杂性的数量将是荒谬的,没有实际的保证它的工作。

于 2015-03-10T15:24:52.637 回答