全局变量的作用域是全局,即可以在任何函数中使用;局部变量的作用域是局部的,不能离开函数被调用,甚至于有的局部变量的作用域还不到一个函数。
为了说明这个问题,我们来看一段函数:
#include
int g_count;
void set_count(int value)
{
g_count = value;
}
int main(int args, char** argv)
{
int s_count;
{
int ss_count;
printf("ss_count = %d\n", ss_count);
}
printf("g_count = %d\n", g_count);
printf("s_count = %d\n", s_count);
printf("ss_count = %d\n", ss_count);
set_count(100);
printf("g_count = %d\n", g_count);
return 0;
}
此时在GCC中编译上述代码,编译器有错误返回。这说明局部变量ss_count的作用域在花括号之内,还没有达到整个main函数。
去掉花括号内的代码,如下:
#include
int g_count;
void set_count(int value)
{
g_count = value;
}
int main(int args, char** argv)
{
int s_count;
printf("g_count = %d\n", g_count);
printf("s_count = %d\n", s_count);
set_count(100);
printf("g_count = %d\n", g_count);
return 0;
}
对应的汇编代码
.file "global.c"
.text
.globl _set_count
.def _set_count; .scl 2; .type 32; .endef
_set_count:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl %eax, _g_count
popl %ebp
ret
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "g_count = %d\12\0"
LC1:
.ascii "s_count = %d\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl _g_count, %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $100, (%esp)
call _set_count
movl _g_count, %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
.comm _g_count, 16 # 4
.def _printf; .scl 3; .type 32; .endef
通过阅读汇编代码,可以发现语句:
.comm _g_count, 16
这是全局变量g_count的定义部分,全局变量g_count被编译器定义为已初始化全局变量。而局部变量s_count 的定义则是这样的:
subl $24, %esp
此时s_count只是栈空间上的一小块空间而已,而且这段空间并没有经过初始化,所有打印s_count应该是一个随机值,这个值在编译的时候就已经决定了。