2012-11-28 15 views
4

我想了解extern和全局變量聲明在頭文件中的用法,所以我想出了下面用C寫的測試程序。「多值定義的價值」編譯C程序與未初始化的全局在g ++中但不是gcc

main.c文件

//main.c 
#include "global.h" 
#include <stdio.h> 

int nExternValue = 6; 

int main(int argc, char* argv[]) 
{ 
    printf("%d \n", nValue); 
    printf("%d \n", nExternValue); 

    AddToValue(); 

    printf("%d \n", nValue); 
    printf("%d \n", nExternValue); 
} 

的global.h文件

#ifndef _GLOBAL_H 
#define _GLOBAL_H 

//WRONG! do not declare a variable here 
int nValue; 

//OK! extern variable makes it a global accessable variable 
extern int nExternValue; 

//OK! function prototype can be placed in h file 
int AddToValue(); 

#endif 

和它實現了AddToValue功能的AddValue.c文件。

#include "global.h" 

int AddToValue() { 
    nValue++; 
    nExternValue++; 
} 

我編譯使用gcc的應用程序,並運行它:

$ gcc main.c AddValue.c -o test 
$./test 
0 
6 
1 
7 

我定義g遵守應用++,得到了下面的鏈接器錯誤:

$ g++ main.c AddValue.c -o test 
/tmp/ccFyGDYM.o:(.bss+0x0): multiple definition of `nValue' 
/tmp/cc3ixXdu.o:(.bss+0x0): first defined here 
collect2: ld returned 1 exit status 

爲什麼沒有gcc鏈接器產生一個錯誤?我雖然nValue變量將被多次聲明,並會產生一個錯誤!

$ gcc --version 
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ g++ --version 
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+0

當您在serveral的* .c文件一個是* .h文件,你會被宣告幾次相同的變量。爲避免這種情況,最好不要在* .h文件中聲明全局變量,而應在* .c文件中聲明全局變量。 – yeyo

+1

@Kira我認爲這裏的問題是**爲什麼gcc鏈接器不會產生多重聲明作爲錯誤?** – shinkou

+0

@shinkou的確,但這就是爲什麼我發表了評論,而不是一個答案,以防萬一他需要修復問題,而他等待真正的答案。 – yeyo

回答

5

C和C++是不同的語言。例如,上述程序是一個有效的C程序,但是格式不正確的C++程序。你違反了C++的一個定義規則。在C中沒有對應的規則。當使用gcc編譯時,您正在將上述文本編譯爲C程序。使用g ++編譯時,您正在將上述文本編譯爲C++程序。

+0

AnT表示它也是無效的C,儘管附錄J中提到了一個常見的擴展:http://stackoverflow.com/a/3692486/895245 –

+0

C具有單一定義規則,並且該程序也不是有效的C程序。 (「nValue」有兩個定義)。 –

3

使用gcc進行編譯時,未初始化的全局變量(例如nValue)將被視爲常用符號。在不同的編譯單元中發生的相同的通用符號將在鏈接期間合併。如果用g ++編譯(這意味着源程序將被視爲C++程序),未初始化的全局變量將默認初始化爲默認值0.由於global.h包含在多個源文件中,因此編譯器會考慮定義符號nValue多次。

也請看看這篇文章: Why uninitialized global variable is weak symbol?