2010-03-27 76 views
5

以下兩個聲明有什麼區別?我認爲它們是相當的,但第一個樣本有效,第二個樣本沒有。我的意思是它編譯並運行,但位圖顯示代碼顯示爲空白。我還沒有穿過它,但我錯過了明顯的東西? GUI_BITMAP是描述位圖的簡單結構。這是VC++ 2005,但我認爲它也在VC++ 2008中失敗。抓我的頭就這一個...C++中的extern關鍵字問題

示例1:

extern "C" const GUI_BITMAP bmkeyA_cap_active; 
extern "C" const GUI_BITMAP bmkeyA_cap_inactive; 

示例2:

extern "C" 
{ 
    const GUI_BITMAP bmkeyA_cap_active; 
    const GUI_BITMAP bmkeyA_cap_inactive; 
}; 

編輯:更多的探索表明,第二個例子創建結構,而第一個是指外部結構。第二個示例應該無法鏈接,因爲在全局範圍內有兩個具有相同名稱的變量。但它不會,它會發送一個零填充結構到放棄的顯示代碼。嗯.....

編輯2:通過另一個編譯器(IAR)運行相同的代碼實際上無法在示例2上編譯,並且出現關於缺少默認構造函數的錯誤。所以我猜測有關於「extern」關鍵字,結構和C++的細節我沒有得到。如果外部區域中的東西是功能,那麼這兩個樣本是相同的?

回答

3

您的鏈接器可能會默默解決背後的重複符號。您可能會從供應商那裏獲得靜態庫,並且必須將它們與您的程序鏈接起來 - 如果您有兩個這樣的庫並且它們都定義了一個通用符號,那麼該解決方案的解決方案是什麼?鏈接器會解決這個問題,選擇一個或另一個定義,然後讓你處理這個影響。你如何處理你的應用程序的鏈接階段?如果直接鏈接.o文件,而不是在鏈接最終應用程序之前將其放入中間庫,則可能會獲得更好的結果。

的ARM文檔This page描述的問題很好 - 我希望類似的行爲是發生在你的情況:

在不同庫對象一個符號的多個定義不一定檢測。一旦鏈接器爲符號找到合適的定義,就停止尋找其他符號。假設包含重複符號的對象因其他原因未加載,則不會發生錯誤。這是有意的,在某些情況下特別有用。

編輯:更多的搜索已止跌回升,這個問題是因爲違反了「One Definition Rule」造成的,並因此不需要編譯器/連接器,通知您的問題。這使您的問題成爲this one的重複。

+0

感謝您的回覆,但這裏沒有使用庫對象,這全是我的代碼,它是C和C++的混合體。我的原始問題仍然存在 - 樣本1和樣本2有什麼區別 - 我認爲它們應該生成完全相同的代碼?如果事情是功能而不是結構 - 它們是相同的東西,對吧? – Jeff 2010-03-27 13:44:42

+1

@傑夫,你的問題的快速答案是,不,這兩個不一樣,這就是爲什麼你看到問題。在第二種情況下,您只是修改'{}'中的語句以使用C的鏈接約定。在第一個例子中,你正在做* plus *表示變量是在其他地方聲明的。 http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx – 2010-03-27 17:31:45

0

第二個例子可能等同於第一個在const前面有一個額外的extern。在第一種情況下,編譯器可能組合了extern的兩種用法。在第二種情況下,我會假設編譯器不會出於任何原因而在外部範圍外部出現任何東西。