看c專家編程,有說存儲類型一直不太清楚。看到一篇文章講解c的存儲類型,講解了c語言中的各種變量的存儲類型,而且是從進程、內存的角度講解的,以前從沒有這樣理解過,覺得挺有用的,在這里轉載過來。
首先要來理解一下可執行文件加載進內存后形成的進程在內存中的結構,如下圖:

代碼區:存放CPU執行的機器指令,代碼區是可共享,並且是只讀的。
數據區:存放已初始化的全局變量、靜態變量(全局和局部)、常量數據。
BBS區:存放的是未初始化的全局變量和靜態變量。
棧區:由編譯器自動分配釋放,存放函數的參數值、返回值和局部變量,在程序運行過程中實時分配和釋放,棧區由操作系統自動管理,無須程序員手動管理。
堆區:堆是由malloc()函數分配的內存塊,使用free()函數來釋放內存,堆的申請釋放工作由程序員控制,容易產生內存泄漏。
c語言中的存儲類型有auto, extern, register, static 這四種,存儲類型說明了該變量要在進程的哪一個段中分配內存空間,可以為變量分配內存存儲空間的有數據區、BBS區、棧區、堆區。下面來一一舉例看一下這幾個存儲類型:
1. auto存儲類型
auto只能用來標識局部變量的存儲類型,對於局部變量,auto是默認的存儲類型,不需要顯示的指定。因此,auto標識的變量存儲在棧區中。示例如下:
- #include <stdio.h>
- int main(void)
- {
- auto int i=1; //顯示指定變量的存儲類型
- int j=2;
- printf("i=%d\tj=%d\n",i,j);
- return 0;
- }
2. extern存儲類型
extern用來聲明在當前文件中引用在當前項目中的其它文件中定義的全局變量。如果全局變量未被初始化,那么將被存在BBS區中,且在編譯時,自動將其值賦值為0,如果已經被初始化,那么就被存在數據區中。全局變量,不管是否被初始化,其生命周期都是整個程序運行過程中,為了節省內存空間,在當前文件中使用extern來聲明其它文件中定義的全局變量時,就不會再為其分配內存空間。
示例如下:
- #include <stdio.h>
- int i=5; //定義全局變量,並初始化
- void test(void)
- {
- printf("in subfunction i=%d\n",i);
- }
- #include <stdio.h>
- extern i; //聲明引用全局變量i
- int main(void)
- {
- printf("in main i=%d\n",i);
- test();
- return 0;
- }
- $ gcc -o test test.c file.c #編譯連接
- $ ./test #運行
- 結果:
- in main i=5
- in subfunction i=5
3. register存儲類型
聲明為register的變量在由內存調入到CPU寄存器后,則常駐在CPU的寄存器中,因此訪問register變量將在很大程度上提高效率,因為省去了變量由內存調入到寄存器過程中的好幾個指令周期。如下示例:
- #include <stdio.h>
- int main(void)
- {
- register int i,sum=0;
- for(i=0;i<10;i++)
- sum=sum+1;
- printf("%d\n",sum);
- return 0;
- }
4. static存儲類型
被聲明為靜態類型的變量,無論是全局的還是局部的,都存儲在數據區中,其生命周期為整個程序,如果是靜態局部變量,其作用域為一對{}內,如果是靜態全局變量,其作用域為當前文件。靜態變量如果沒有被初始化,則自動初始化為0。靜態變量只能夠初始化一次。示例如下:
- #include <stdio.h>
- int sum(int a)
- {
- auto int c=0;
- static int b=5;
- c++;
- b++;
- printf("a=%d,\tc=%d,\tb=%d\t",a,c,b);
- return (a+b+c);
- }
- int main()
- {
- int i;
- int a=2;
- for(i=0;i<5;i++)
- printf("sum(a)=%d\n",sum(a));
- return 0;
- }
- $ gcc -o test test.c
- $ ./test
- a=2, c=1, b=6 sum(a)=9
- a=2, c=1, b=7 sum(a)=10
- a=2, c=1, b=8 sum(a)=11
- a=2, c=1, b=9 sum(a)=12
- a=2, c=1, b=10 sum(a)=13
6. 字符串常量
字符串常量存儲在數據區中,其生存期為整個程序運行時間,但作用域為當前文件,示例如下:
- #include <stdio.h>
- char *a="hello";
- void test()
- {
- char *c="hello";
- if(a==c)
- printf("yes,a==c\n");
- else
- printf("no,a!=c\n");
- }
- int main()
- {
- char *b="hello";
- char *d="hello2";
- if(a==b)
- printf("yes,a==b\n");
- else
- printf("no,a!=b\n");
- test();
- if(a==d)
- printf("yes,a==d\n");
- else
- printf("no,a!=d\n");
- return 0;
- }
- $ gcc -o test test.c
- $ ./test
- yes,a==b
- yes,a==c
- no,a!=d
總結如下表:

