當時寫了一個相似於下面的枚舉:php
#ifndef TEST_ENUM_H_web
#define TEST_ENUM_H_ui
enum {spa
TEST_FLAG1_E,.net
TEST_FLAG2_E,unix
TEST_FLAG_NRblog
} TEST_E;ip
#endif產品
當時在enum關鍵字前面遺漏了「typedef」。我通常習慣於使用typedef,這樣能夠直接使用TEST_E而不是enum TEST_E。it
該頭文件會被其它源文件引用。因爲在代碼中,沒有須要定義枚舉變量的地方,只是使用枚舉的值,因此當時沒有發現遺漏「typedef」。編譯也沒有任何問題。
可是當天的build卻沒有經過。錯誤信息顯示定義了重複的TEST_E,所以編譯失敗。因爲與美國的時差問題,這個錯誤由美國的一同事修改了。他陳述的錯誤緣由是:這樣的枚舉聲明對於C來講,是沒有問題的。——咱們的核心代碼都是C編寫的。
可是對於C++,會認爲不是聲明而是定義,定義了一個TEST_E變量。結果致使重複定義了該變量。——有一部分web功能代碼是使用C++編寫的。
當我早上看到他的說明時,首先要對break build表示歉意;第二也鄙視了一下該產品的makefile——我剛剛加入這個產品組。這樣的makefile,爲了檢查checkin,我不得不先make clean才能保證全部的代碼被編譯。這樣花費的時間太多了。第三,我纔想起web的這部分功能是使用C++的。第四,寒一下本身,竟然漏寫了typedef;第五,也有些好奇C++的編譯爲何出錯。
可是當我看到他的陳述時,我知道他確定錯了。對於C和C++來講,枚舉enum的區別不會這麼大。對於上面那個枚舉類型定義,因爲遺漏了typedef,因此這裏的TEST_E不管是C仍是C++來講,都會把TEST_E看成一個枚舉變量處理,也就是一個全局變量。那麼引發問題的緣由是由於C和C++對於沒有初始值的全局變量的處理不一樣——真拗口,而最後的編譯連接行爲不一樣。
看下面的簡單示例:
文件test1.c
int a;
int main()
{
return 0;
}
文件tes2.c
int a;
編譯
[fgao@fgao-vm-fc13 test]$ gcc -g -Wall test1.c test2.c
[fgao@fgao-vm-fc13 test]$
編譯沒有任何的warning和error。對於沒有初始值的全局變量,其爲弱符號。對於多個弱符號定義,在C的連接階段不會有任何問題。你們能夠參見我這篇文章經過未初始化全局變量,研究BSS段和COMMON段的不一樣 http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=2888209
在這篇文章中,我解釋了爲何C容許多個弱符號存在
下面將其視爲C++代碼,使用g++編譯:
[fgao@fgao-vm-fc13 test]$ g++ -g -Wall test1.c test2.c
/tmp/ccQdTwRi.o:(。bss+0x0): multiple definition of `a'
/tmp/cc7SOWD1.o:/home/fgao/works/test/test1.c:4: first defined here
collect2: ld returned 1 exit status
一樣是沒有初始值的全局變量,在C++的連接階段就會報錯。對於C++爲何報錯,這確定是因爲C++的連接機制有關。目前我並不清楚緣由,有了解的朋友請賜教。謝謝。