最近在看多文件編程的時候遇到的一個問題,本來以為理解了聲明和定義的區別(然而並沒有····),也算是重新認識了一次聲明和定義,下面上代碼
聲明和定義:有分配空間的叫定義,沒分配空間的叫聲明
定義:表示創建變量或分配存儲單元
聲明:說明變量的性質,但並不分配存儲單元
情形一:在源文件(.c)中(函數內)
int a;//定義
extern int a;//聲明
第一個int a是定義,分配了存儲空間(其實包括了聲明和定義兩個步驟,可以叫"定義性聲明"),第二個 extern int a是聲明(也叫"引用性聲明"),沒有分配存儲空間
關於extern的使用,感興趣的讀者可以看一下另一片隨筆:extern的使用詳解(多文件編程)——C語言
聲明可以多次,定義只能有一次
意思是在源文件(.c)中可以多次聲明同一個變量,例如在編譯階段是不會報錯的
情形二:在源文件(.c)中(函數外)
編譯結果:
這里的int a;放在函數外,沒有出現重定義的錯誤,並不意味着int a就不是定義了,int a仍然是定義,編譯階段沒有報錯了原因在於全局變量沒有賦初值,沒賦初值的全局變量,那么在目標文件中是不會為
這個全局變量分配空間的,它被放在BSS段(如果是賦初值的全局變量,那么放在data段),BSS段在目標文件中是沒有的(這個就是編譯階段不會報錯的原因),意味着沒賦初值的全局變量不占磁盤空間,
當程序加載運行時,就會為bss
段中的數據分配內存進行初始化了(起到了節省磁盤空間的作用),上面說了BSS段的數據不占磁盤空間,那么它的大小和符號存在哪呢? bss
段占據的大小存放在ELF文件格式
中的段表(Section Table)中,段表存放了各個段的各種信息,比如段的名字、段的類型、段在elf文件中的偏移、段的大小等信息
(感謝園友:SD8086 指出隨筆中的錯誤)
(對內存映像感興趣的讀者可以看下這兩篇文章:bss段不占據磁盤空間的理解、大內高手—全局內存)
情形三:在頭文件(.h)中
在頭文件中的聲明和定義和在源文件中函數外的聲明和定義相同,下面為測試結果
修改頭文件后
從上面可以看出int a在頭文件中仍然是定義,只不過和全局變量定義相同,只要沒有賦初值,編譯階段就不會報錯