2016-01-29 55 views
3

我是新來的extern的概念。今天在工作中,我遇到了大量在頭文件中聲明的extern函數; foo.h.在一些文件夾中,我找到了一個foo.c文件,其中包含了所述函數的定義,但它不包含#include foo.h。當我回到家時,我決定玩弄外部存儲類的例子。在讀完「C書」後,我想到了這一點。爲什麼我需要聲明這個函數extern。它沒有它的作品

這是我不期望工作。但它的確如此。

的main.c

#include <stdio.h> 

int data; 

int main() 
{ 

    data = 6; 

    printf("%d\n", getData()); 

    data = 8; 

    printf("%d\n", getData()); 
    return 0; 
} 

externs.c

int getData() 
{ 
    extern int data; 
    return data; 
} 

慶典

gcc main.c externs.c -o externs 

我不認爲這會工作b因爲該功能在技術上並非在main之前定義的(或者至少是冗長的)。這是否工作,因爲int getData()的默認存儲類是extern?如果是這樣,爲什麼即使打擾下面的例子(類似於我在工作中看到的)?

main2.c

#include <stdio.h> 
#include "externs.h" 

int data; 

int main() 
{ 

    data = 6; 

    printf("%d\n", getData()); 

    data = 8; 

    printf("%d\n", getData()); 
    return 0; 
} 

externs.h

#ifndef _EXTERNSH_ 
#define _EXTERNSH_ 

extern int getData(); 

#endif 

externs.c

int getData() 
{ 
    extern int data; 
    return data; 
} 

個慶典

gcc main2.c externs.c -o externs 
+0

您可以在每種情況下添加或評論輸出嗎? – Grantly

回答

5

函數隱extern。你可以通過將它們聲明爲static來改變它。

你是對的,這是多餘的extern int getData();相比int getData();但有些人覺得這提高了代碼的清晰度說。

請注意,由於C99,你的第一個例子是格式不正確。它調用getData而沒有聲明該函數。在C89中,執行了一個隱含的int getData();聲明,但自從C99被刪除。使用編譯器開關-std=c99 -pedantic來測試。

4

默認情況下,GCC 4.x或更低版本以C89/C90兼容模式編譯,不需要在使用前聲明函數。未聲明的功能被推斷爲返回類型爲int。默認情況下,GCC 5.x或更高版本以C11兼容模式進行編譯,這需要在使用之前聲明函數 - 就像C99一樣。

鑑於代碼編譯沒有抱怨,我們可以推斷出您正在使用GCC 4.x.

即便如此,您並沒有義務提供完整的原型,儘管您不會愚蠢。我經常編譯代碼的選項:

gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \ 
    -Wold-style-definition -Wold-style-declaration … 

我懷疑有一些冗餘在那裏,但那些選擇搭上許多的問題之前,我周圍運行的代碼。

+0

感謝您的回答。 +1爲gcc標籤。 M.M.擊敗你1分鐘:x – atomSmasher

相關問題