静态全局和本地标识符的阴影

时间:2014-03-01 21:05:49

标签: c

以下程序是在课堂上发布的练习工作表上。我们被要求提供它的输出,但是根据我对链接的理解,file2.c不应该有两个静态标识符b的实例,但是程序会编译一个警告并运行得很好。我的问题是,为什么允许这样做?我认为静态链接的目的是能够在该文件中的任何位置访问标识符?

澄清:问题是关于file2.c:有两个“static int b”声明。为什么允许这样做?

/ * file1.c * /

#include <stdio.h> 

extern int a; 
static int b; 

void f(int); 
void g(void); 

int main() { 

  a = 10; 
  b = 20; 
  f(a); 
  f(b); 
  g(); 
  printf("main: %d %d\n", a, b); 

  return 0; 
} 

/ * file2.c * /

include <stdio.h> 

int a; 
static int b; 

void f(int c) { 
  static int b = 5; 

  a += b; 
  b += c; 
  printf("f: %d %d\n", a , b ) ; 

} 

void g(void) { 
  a += 5; 
  b = 10; 
  printf("g: %d %d\n", a , b); 

} 

提前感谢您的任何帮助(这是我第一次发帖,所以如果有格式错误我会道歉!)。

1 个答案:

答案 0 :(得分:3)

编译器为每个全局静态变量创建一个不同的实例,即使你有几个具有相同名称的变量也是如此。

实际上,编译器(或可能是预处理器)根据声明它的源文件的名称隐式更改每个这样的变量的名称。

您可以通过在头文件中声明全局静态变量来证明这一点,然后将此头文件包含在几个不同的源文件中。尝试在每个源文件中将其设置为不同的值,您将看到此变量在每个源文件中保留其不同的值。

如果您想要在多个源文件中访问全局变量的相同实例,那么您应该克制声明它static

  • 如果在头文件中声明它,则使用extern作为前缀,并在每个使用此变量的源文件中包含头文件。
  • 如果您在源文件中声明它,则必须在使用此变量的每个其他源文件中将其声明为extern

外部全局变量的地址仅在链接期间确定。这与以下情况形成对比,其中变量的地址在编译期间确定

  • 本地变量
  • 静态局部变量
  • 静态全局变量
  • 非外部全局变量

我认为术语static linkage指的是编译对象(或库)在构建过程中与可执行图像的链接,而不是引用的dynamic linkage将编译代码(也称为DLL)链接到可执行映像仅在运行时


<强>更新

在阅读澄清之后,我理解唯一的问题是局部变量和同名的全局变量(static属性对此问题没有任何影响。)

在函数内部,对于具有相同名称的全局变量,局部变量始终是“编译器首选”。换句话说,在函数f中,变量b上的所有操作都应用于局部变量而不是全局变量。