以下程序在类里面给出的练习工作表上。我们被要求提供它的输出,但根据我对链接的理解,file2.c 不应该有静态标识符 b 的两个实例,但程序编译时带有警告并且运行正常。我的问题是,为什么允许这样做?我认为静态链接的目的是能够访问该文件中任何地方的标识符?
澄清:问题是关于 file2.c 的:有两个“static int b”声明。为什么允许这样做?
/* 文件1.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;
}
/* 文件2.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);
}
提前感谢您的帮助(这是我第一次发帖,所以如果有格式错误,我深表歉意!)。
最佳答案
编译器会为每个全局静态变量创建一个不同的实例,即使您有多个具有相同名称的此类变量也是如此。
事实上,编译器(或者可能是预处理器)根据声明它的源文件的名称隐式更改每个此类变量的名称。
您可以通过在头文件中声明一个全局静态变量来证明这一点,然后将这个头文件包含在几个不同的源文件中。尝试在每个源文件中将其设置为不同的值,您会看到此变量在每个源文件中都保留其不同的值。
如果您希望在多个源文件中访问全局变量的相同实例,那么您应该避免将其声明为static
:
- 如果您在头文件中声明它,则使用
extern
作为前缀,并在每个使用此变量的源文件中包含头文件。 - 如果您在源文件中声明它,则必须在每个使用此变量的其他 源文件中将其声明为
extern
。
外部全局变量的地址仅在链接期间确定。这与以下情况形成对比,在这些情况下,变量的地址是在编译期间确定的:
- 局部变量
- 静态局部变量
- 静态全局变量
- 非外部全局变量
我相信术语静态链接
是指在构建过程中将已编译对象(或库)链接到可执行镜像中,而不是动态链接
,是指仅在运行时将已编译代码(也称为 DLL)链接到可执行镜像。
更新:
阅读您的说明后,我了解到唯一的问题是局部变量和同名全局变量(static
属性对这个问题没有影响)。
在函数内部,局部变量总是比同名的全局变量“更受编译器青睐”。换句话说,在函数 f
中,对变量 b
的所有操作都应用于局部变量而不是全局变量。
关于c - 隐藏静态全局和局部标识符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22120362/