以下程序是在课堂上发布的练习工作表上。我们被要求提供它的输出,但是根据我对链接的理解,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);
}
提前感谢您的任何帮助(这是我第一次发帖,所以如果有格式错误我会道歉!)。
答案 0 :(得分:3)
编译器为每个全局静态变量创建一个不同的实例,即使你有几个具有相同名称的变量也是如此。
实际上,编译器(或可能是预处理器)根据声明它的源文件的名称隐式更改每个这样的变量的名称。
您可以通过在头文件中声明全局静态变量来证明这一点,然后将此头文件包含在几个不同的源文件中。尝试在每个源文件中将其设置为不同的值,您将看到此变量在每个源文件中保留其不同的值。
如果您想要在多个源文件中访问全局变量的相同实例,那么您应该克制声明它static
:
extern
作为前缀,并在每个使用此变量的源文件中包含头文件。extern
。外部全局变量的地址仅在链接期间确定。这与以下情况形成对比,其中变量的地址在编译期间确定:
我认为术语static linkage
指的是编译对象(或库)在构建过程中与可执行图像的链接,而不是引用的dynamic linkage
将编译代码(也称为DLL)链接到可执行映像仅在运行时。
<强>更新强>
在阅读澄清之后,我理解唯一的问题是局部变量和同名的全局变量(static
属性对此问题没有任何影响。)
在函数内部,对于具有相同名称的全局变量,局部变量始终是“编译器首选”。换句话说,在函数f
中,变量b
上的所有操作都应用于局部变量而不是全局变量。