假设以下最少代码:
#include <stdio.h>
char character = 'c';
int main (void)
{
char character = 'b';
printf("The current value of head is %c", character);
}
我在character
中改写了main
,
那么c
怎么了?它会自动销毁还是永久保留在内存中?
这句话引起了我的兴趣:“ C中的变量不过是命名的内存块而已。”
答案 0 :(得分:25)
“ shadowing”全局character
变量对main
函数隐藏了该变量,但它仍将是程序的一部分。
如果将character
变量声明为static
,则编译器可能会警告不要使用character
变量,并且character
将被优化。
但是,character
变量未声明为static
;编译器将假设character
变量可以从外部访问,并将character
变量保留在内存中。
编辑:
如@Deduplicator所述,如果允许,链接器的优化和设置可以从最终可执行文件中忽略该变量。但是,这是一个边缘情况,不会“自动”发生。
答案 1 :(得分:13)
您有两个分别名为character
的变量:一个在文件作用域中设置为'c',其生存期是程序的生存期,在main
中一个变量设置为'b',其生存期是它的范围。
character
中main
的定义在文件范围内屏蔽,因此只能访问后者。
答案 2 :(得分:6)
补充其他答案:
尝试一下,您将了解:
#include <stdio.h>
char character = 'c';
void Check()
{
printf("Check: c = %c\n", character);
}
int main(void)
{
char character = 'b';
printf("The current value of head is %c\n", character);
Check();
}
答案 3 :(得分:5)
它将继续存在(直到程序死亡,就像任何静态存储变量一样),您仍然可以使用它:
#include <stdio.h>
char character = 'c';
int main (void)
{
char character = 'b';
printf("The current value of head is '%c'\n", character);
{
extern char character;
//in this scope, overrides the local `character` with
//the global (extern?) one
printf("The current value of head is '%c'\n", character);
}
printf("The current value of head is '%c'\n", character);
}
/*prints:
The current value of head is 'b'
The current value of head is 'c'
The current value of head is 'b'
*/
对于static
全局变量,本地extern声明不能可靠/方便地工作,尽管您仍然可以通过指针或单独的函数来访问它们。
(
为什么static char character='c'; int main(){ char character='b'; { extern char character; } }
与全局static
不可靠?
6.2.2p4似乎也想使其适用于静态变量,但是措辞含糊(先前的声明没有链接,而另一个声明具有静态/外部链接,那么现在怎么办?)。
对于在存储类说明符extern中声明的标识符 可以看到该标识符的先前声明的范围,31) 如果先前声明指定了内部或外部链接,则 后面声明中标识符的链接与 事先声明中指定的链接。如果没有事先声明 可见,或者如果先前的声明未指定任何链接,则 标识符具有外部链接。
我的clang 6.0.0使用static char character='b';
接受它,但我的gcc 7.3.0不接受。
感谢Eric Postpischil指出了static
也可以使用的不确定性。
)
答案 4 :(得分:3)
在character
中声明main
之后,在该函数中对character
的任何引用都指向那个,而不是全局范围内的那个。我们称之为 shadowing 。
对于内存的影响,由于该语言采用了 as-if 规则,因此您不能说:编译器可能会优化为
#include <stdio.h>
int main()
{
printf("The current value of head is b");
}
例如。
答案 5 :(得分:2)
Form1
一切都清楚了。它并没有被破坏,只是被遮盖了。
输出:
head的当前值为b
c
答案 6 :(得分:1)
通常,全局变量将保留。由于您的局部变量仅会遮盖名称,因此不会影响存储。
但是它也可能取决于链接器设置。链接器可以优化未使用的全局变量。
答案 7 :(得分:1)
尽管全局变量从程序执行的开始到结束都存在,但不能自动访问它们。
从文件中定义或声明全局变量的位置开始,直到文件末尾都可以访问全局变量。
如果在函数作用域中定义了一个具有相同名称的变量,则该全局变量将存在,但将不可访问。