2013-06-23 85 views
3

我最常用的基於頭的庫使用放置在庫的名稱空間(BigNum)中的全局變量。 變量的定義如下:只要我有這個定義全局變量和鏈接問題

namespace BigNum{ 
/** 
* __Some lower powers of ten prestored for fast runtime lookup.__*/ 
const uintmax_t pten[20]={ 
1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, .... 
}; 
} 

一切正常,在我的main.cpp文件(真的是唯一nonheader文件我的測試中配置了),我的頭都extern uintmax_t pten[];在他們(如果他們還包括cstdint,其中uintmax_t是typedefined)。

但是,我會喜歡在其他地方有這個定義,所以我創建了一個global.cpp文件,其中包含上面的內容,並確保我的Makefile將其鏈接到其餘文件。 有趣的是,在main.cpp和global.cpp中編譯pten的定義工作正常(我會期望雙重定義錯誤),但是在main.cpp中將定義從global.cpp中移除會導致鏈接錯誤。

我檢查了生成的global.o,它確實包含pten符號(它的損壞形式)。試圖以任一順序手動鏈接main.o和global.o失敗。

任何想法?

附加信息: 下面是一個演示問題的基本示例。

的main.cpp

#include <cstdint> 
    #include <iostream> 

    namespace BigNum{ 
    extern const uintmax_t pten[]; 
    } 
    int main(int argc, const char *argv[]) 
    { 
     using namespace std; 

     cout<<BigNum::pten[0]<<endl; 
     return 0; 
    } 

global.cpp

#include <cstdint> 

    namespace BigNum{ 
    /** 
    * __Some lower powers of ten prestored for fast runtime lookup.__ 
    */ 
    const uintmax_t pten[20]={ 
     1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, 1000000LU, 10000000LU, 100000000LU, 1000000000LU, 10000000000LU, 100000000000LU, 1000000000000LU, 10000000000000LU, 100000000000000LU, 1000000000000000LU, 10000000000000000LU, 100000000000000000LU, 1000000000000000000LU, 10000000000000000000LU 
    }; 
    } 

彙編:

g++ -std=c++0x -c global.cpp -o global.o 
    g++ -std=c++0x -c main.cpp -o main.o 
    g++ -std=c++0x global.o main.o 

>main.o: In function `main': 
>main.cpp:(.text+0x12): undefined reference to `BigNum::pten' 
>collect2: ld returned 1 exit status 
+2

*鏈接*錯誤?你沒有告訴我們很多,但如果你告訴我們的是準確的,我不能重現這個錯誤,也不能理解它。如果你給我們一個最小的完整例子,我們可能可以清除它。 – Beta

+0

我的心靈感應調試能力告訴我你在BigNum命名空間中沒有extern的頭部聲明? – Petesh

+0

@Beta示例添加。感謝您的關注。 – PSkocik

回答

2

你在global.cpp代碼應該是:

#include <cstdint> 

namespace BigNum{ 
/** 
* __Some lower powers of ten prestored for fast runtime lookup.__ 
*/ 
extern const uintmax_t pten[]; //This should go in a common header file 
const uintmax_t pten[20]={ 
    1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, 1000000LU, 10000000LU, 100000000LU, 1000000000LU, 10000000000LU, 100000000000LU, 1000000000000LU, 10000000000000LU, 100000000000000LU, 1000000000000000LU, 10000000000000000LU, 100000000000000000LU, 1000000000000000000LU, 10000000000000000000LU 
}; 
} 

檢查this guide:通常情況下,你會把extern const uintmax_t pten[];在一個單獨的公共頭文件。

+0

謝謝。它有兩種方式:在定義中使用extern,在main.cpp中使用extern聲明,或者在兩個文件中使用非extern定義和extern定義。我確實有一個共享頭文件,其中包含了pten的extern聲明,但我沒有將其包含在global.cpp中。如果我有,那就解決了這個問題。 ;-) – PSkocik

-1

問題解決了。 原來,與函數不同,所有全局變量都不可見於其他編譯單元。爲了使它們可見,關鍵字extern也必須在其定義中使用(在global.cpp中)。

+1

這是*不可能*。不要混淆聲明和定義。當你使用'extern'時總是一個聲明。你在哪裏定義你的變量?請閱讀[this](http://en.wikipedia.org/wiki/External_variable)。 – Antonio

+0

「與其他編譯單元不同,所有全局變量都是靜態的,因此不可見」 - 該語句是* false *。 –

+0

@ ThorX89添加「extern」的代碼偶爾會有點作用,這主要是因爲您正在爲變量初始化/分配內存。 – Antonio