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