.data:己初始化的全局C变量,局部C变量在运行时被保存在栈中,既不出现在.data段中,也不出现在.bss段中。
$gcc main.c -g $readelf -a a.out ...
49: 0804a01c 4 OBJECT LOCAL DEFAULT 24 b
50: 0804a020 4 OBJECT LOCAL DEFAULT 24 a.1707
...
65: 08048570 4 OBJECT GLOBAL DEFAULT 16 A
66: 0804a018 4 OBJECT GLOBAL DEFAULT 24 a
...
78: 0804a02c 4 OBJECT GLOBAL DEFAULT 25 c
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[14] .text PROGBITS 08048390 000390 0001bc 00 AX 0 0 16
[16] .rodata PROGBITS 08048568 000568 00001c 00 A 0 0 4
[24] .data PROGBITS 0804a010 001010 000014 00 WA 0 0 4
[25] .bss NOBITS 0804a024 001024 00000c 00 WA 0 0 4
从上面的readelf的输出可以看到.data段从地址0x0804a010,长度为0x14,也就是到地址0x804a024结束,在.data段中有三个变量,a,b,和a.1707。
a是一个GLOBAL的符号,而b被static关键字修饰了,导致它成为一个LOCAL的符号,所以static在这里的作用是声明b这个符号为 LOCAL的,不被链接器处理,在下一章我们会看到,如果把多个目标文件链接在一起,LOCAL的符号只能在某一个目标文件中定义和使用,而不能定义在一个目标文件中却在另一个目标文件中使用。一个函数定义前面也可以用static修饰,表示这个函数名符号是LOCAL的。
还有一个a.1589是什么呢?它就是main函数中的static int a。函数中的static变量不同于以前我们讲的局部变量,它并不是在调用函数时分配,在函数返回时释放,而是像全局变量一样静态分配,所以用 “static”(静态)这个词。另一方面,函数中的static变量的作用域和以前讲的局部变量一样,只在函数中起作用,比如main函数中的a这个变量名只在main函数中起作用,在别的函数中说变量a就不是指它了,所以编译器给它的符号名加了一个后缀,变成a.1589,以便和全局变量a以及其它函数的变量a区分开。