2017-04-25 54 views
3

此代碼可以編譯和下當前的C標準被很好地定義:理由靜態聲明,接着非靜態聲明允許的,但反過來不行

static int foo(int); 
extern int foo(int); 

該標準規定,在這種情況下(C11:6.2標識符的0.2的聯繫(P4)):

對於 一個範圍,其中該標識符的先前聲明是可見的與存儲類說明的extern聲明的標識符,31) 如果之前的聲明指定了內部或外部鏈接,則後面聲明中標識符的鏈接 與前面聲明中指定的鏈接 相同。 [...]

...這意味着int foo(int)函數被聲明爲static int foo(int)

左右交換這些聲明是這樣的:

extern int foo(int); 
static int foo(int); 

...讓我使用GNU GCC編譯器錯誤:

的 '富' 靜態聲明如下非靜態聲明

我的問題是:什麼是第二種情況下的設計原理是一個錯誤,並沒有像第一個案例那樣處理?我懷疑這與單獨的翻譯單元更容易管理和事實有關。我覺得好像沒有理解這一點,我可以在未來的C項目中面對一些錯誤。

+0

你 '這意味着'INT FOO(INT)'函數聲明'的extern INT FOO(INT)'' 評論是錯誤的。之前的'static'聲明意味着函數是'static'。如果你只在頭文件中聲明外部可見的函數(聲明屬於這個頭文件)並且只在源文件中聲明靜態函數,那麼你將永遠不會遇到問題。頭文件不聲明靜態函數(除非頭文件定義了「靜態內聯函數」)。如果您在編寫代碼的方式上很sl You,只能遇到問題。 C編譯器允許你馬虎,但你不應該。 –

+0

相似的評論適用於變量。不要在源文件中寫入'extern'變量的聲明;它們只屬於頭文件。 –

+0

@JonathanLeffler「先前的靜態聲明意味着該函數是靜態的」。這是正確的,這是一個錯字。編輯。 –

回答

1

我認爲這種混亂說明書的思想是一個extern聲明可以函數內使用,是指一個全局函數或對象,例如,以從另一個識別符具有相同名稱

static double a; // a declaration and definition 

void func(void) { 
    unsigned a; 
    ..... 
    if (something) { 
    extern double a; // refers to the file scope object 

    } 
} 

歧義它而如果你使用static聲明新的東西:

extern double a; // just a declaration, not a definition 
        // may reside elsewhere 
void func(void) { 
    unsigned a; 
    ..... 
    if (something) { 
    static double a; // declares and defines a new object 

    } 
} 
+0

有道理。希望看到其他人先說什麼,但我認爲迄今爲止這是最合理的。 –