2013-10-03 60 views
2

我遇到一些奇怪的行爲(當然,我想這是有解釋),同時試圖交叉編譯一些文件從Debian的一個臂Linux目標,使用:C交叉編譯器鏈接extern聲明爲靜態?

$ arm-linux-gnueabi-gcc --version 

$ arm-linux-gnueabi-gcc (Debian 4.3.5-4) 4.3.5 

在編譯時我得到這些錯誤消息:

dsblock1.c:167: error: non-static declaration of ‘HaveEventIterated_’ follows static declaration 
ss2dym.c:778: error: previous declaration of ‘HaveEventIterated_’ was here 

相對應的線:

ss2dym.c:778 : 
extern long HaveEventIterated_; 

"redeclaration" dsblock1.c:167: 
long HaveEventIterated_=0; 

因此,這裏是我沒有得到的東西: 根據我以爲我知道的東西,變量首先聲明爲extern,是非靜態的。

但是:「extern」聲明在靜態函數中。 所以我的猜測是,這是某種繼承行爲?!

所以,這裏是問題: - 有人可以解釋背景故事,如果我的猜測是正確的? - 有沒有一種簡單的方法來解決這個問題,例如用一個棘手的編譯器標誌,允許嵌套的範圍轉移或其他魔術?

我知道它很可能會創建一個頭並將所有這些extern聲明放到中性空間,但是我已經有了幾百個這樣的錯誤和幾個文件。我已經看到,這段代碼使用MSVC++編譯得很好(它有其他的作用域約束,我知道,但使用arm-g ++時我有更多的問題),所以必須有某種解決方案,比重寫所有這些部分更容易...

BTW:有改變這一切的「重聲明」的範圍一個簡單的方法,因爲我已經在所有的人面前宏喜歡:

MY_MACRO long HaveEventIterated_=0; 

和ATM我-DMY_MACRO=編譯

Soooo any? :)

回答

2

extern關鍵字給出的標識符相同的鏈接作爲先前的可見的聲明,或外部鏈接,如果沒有先前的可見的聲明。 (這是語言的一個奇怪的怪癖,可以肯定的。)

因此,這個問題是最有可能發生因第三(或者我應該說是「第一」)的HaveEventIterated_聲明,編譯器在達到ss2dym.c的778行之前達到。第三個(或第一個)聲明使用關鍵字static給出標識符內部鏈接。第二個聲明,extern,然後給出相同的變量內部鏈接,第三個 - 沒有存儲級關鍵字指定鏈接 - 給出可變的外部鏈接,導致錯誤。

下面是再現問題一個簡單的例子(在不同的gcc,但相同的行爲):

$ cat foo2.c 
static int var; 
extern int var; 
int var = 0; 
$ gcc -c foo2.c 
foo2.c:3: error: non-static declaration of 'var' follows static declaration 
foo2.c:2: error: previous declaration of 'var' was here 

附註:如果先前的可見聲明有沒有聯動,你會得到外部聯繫。這僅重新聲明一個塊,其中該塊外的變量具有自動持續時間,即內部的變量時,會發生,是一個「本地」或「堆」的函數內部變量:

void f(void) { 
    int v; 
    { 
     extern int v; 

這裏有一個先前的可見聲明沒有鏈接,所以最裏面的v有外部鏈接。如果在同一個翻譯單元中有一個v與內部鏈接,則效果不明確。 (當然,沒有人應該首先編寫像f()這樣的代碼,無論如何:-))

+0

它確實是那麼簡單......「第三」聲明謝謝! – beneeng

+0

好解釋+1 – fayyazkl