#include<stdio.h>
static int a=5;
main()
{
static int a=15;
printf("%d\n",a);
}
那么,两个变量a
如何存储在内部存储器中?
具有相同变量名的全局变量和局部变量如何存储在内存中?
#include<stdio.h>
static int a=5;
int main()
{
printf("%p\n",(void *)&a);
static int a=15;
printf("%p\n",(void *)&a);
return 0;
}
上层程序的输出是
0x564e6b67a030
0x564e6b67a034
所以你可以看到它们都存储在不同的地址中。一个是全局变量,另一个是本地变量。
这些名称仅供人类读者感兴趣,编译器/链接器将该代码转换为机器可执行代码。最终目标代码将这些解析为地址,名称不再存在。
编译器以同样的方式区分这些 - 按范围;当同一名称空间中的两个相同符号同时在范围内时,具有最大限制范围的符号是可见的(即可以通过名称访问)。
对于具有外部链接的符号(在您的示例中除了main
之外没有其他符号),编译器会保留符号名称以解析单独编译的模块之间的链接。在完全链接的可执行文件中,符号名称不再存在(调试构建符号元数据除外)。
事情是范围不要让他们陷入困境。第一个具有文件范围,另一个具有块范围。 (它们是不同的变量 - 它们存储在不同的存储器中。)
在块中使用它时 - 编译器检查该引用是否由同一块中的任何内容解析。它得到一个。并做了。
如果它在某个其他函数中 - 如果它没有找到任何名为a
的东西 - 搜索在文件范围内结束,它找到名称a
。这就是故事的结局。
两者都是静态的,其存储持续时间相同他们活到程序存在。但他们的范围不同。如果范围也相同 - 编译器会显示错误消息。
在这里,如果您使用-Wshadow
选项进行编译 - 它将警告您关于变量的阴影。你用那个街区的内部遮住了外面的a
。而已。
讽刺的答案是它们存放在不同的地方。
请记住,变量的名称(通常)不构成编译程序的一部分,因此编译器只遵循变量阴影的常规规则。所以在你的情况下你的print
函数(顺便说一下,这不是标准的C函数 - 你的意思是printf
?)输出在a
中声明的main
。您使用相同名称的事实根本不会打扰编译器。
最后,一旦在a
中遇到另一个声明,C就无法访问全局范围的main
,因为它是static
。 (你可以使用extern
不是静态的。)见How can I access a shadowed global variable in C?