全局變量是C語言語法和語義中一個很重要的知識點,首先它的存在意義需要從三個不同角度去理解:對於程序員來說,它是一個記錄內容的變量(variable);對於編譯/鏈接器來說,它是一個需要解析的符號(symbol);對於計算機來說,它可能是具有地址的一塊內存(memory)。其次是語法/語義:從作用域上看,帶static關鍵字的全局變量范圍只能限定在文件裡,否則會外聯到整個模塊和項目中;從生存期來看,它是靜態的,貫穿整個程序或模塊運行期間(注意,正是跨單元訪問和持續生存周期這兩個特點使得全局變量往往成為一段受攻擊代碼的突破口,了解這一點十分重要);從空間分配上看,定義且初始化的全局變量在編譯時在數據段(.data)分配空間,定義但未初始化的全局變量暫存(tentative definition)在.bss段,編譯時自動清零,而僅僅是聲明的全局變量只能算個符號,寄存在編譯器的符號表內,不會分配空間,直到鏈接或者運行時再重定向到相應的地址上。
我們將向您展現一下,非static限定全局變量在編譯/鏈接以及程序運行時會發生哪些有趣的事情,順便可以對C編譯器/鏈接器的解析原理管中窺豹。以下示例對ANSI C和GNU C標准都有效,筆者的編譯環境是Ubuntu下的GCC-4.4.3。
第一個例子
/* t.h */
#ifndef _H_
#define _H_
inta;
#endif
/* foo.c */
#include <stdio.h>
#include "t.h"
struct{
chara;
intb;
} b = { 2, 4 };
intmain();
voidfoo()
{
printf("foo:\t(&a)=0x%08x\n\t(&b)=0x%08x\n
\tsizeof(b)=%d\n\tb.a=%d\n\tb.b=%d\n\tmain:0x%08x\n",
&a, &b,sizeof b, b.a, b.b, main);
}
/* main.c */
#include <stdio.h>
#include "t.h"
intb;
intc;
intmain()
{
foo();
printf("main:\t(&a)=0x%08x\n\t(&b)=0x%08x\n
\t(&c)=0x%08x\n\tsize(b)=%d\n\tb=%d\n\tc=%d\n",
&a, &b, &c,sizeof b, b, c);
return0;
}
Makefile如下:
test: main.o foo.o
gcc -otest main.o foo.o
main.o: main.c
foo.o: foo.c
clean:
rm*.o test
運行情況:
foo: (&a)=0x0804a024
(&b)=0x0804a014
sizeof(b)=8
b.a=2
b.b=4
main:0x080483e4
main: (&a)=0x0804a024
(&b)=0x0804a014
(&c)=0x0804a028
size(b)=4
b=2
c=0
接下來請看第2頁精彩內容:http://www.linuxidc.com/Linux/2013-10/90910p2.htm