2009-06-20 56 views
3

我碰到一些代碼以下面的方式來可能出現的瑕疵「包括* .c文件」式C編程

//file.c 
#include <stdlib.h> 

void print(void){ 

    printf("Hello world\n"); 
} 

//file main.c 
#include <stdio.h> 
#include "file.c" 

int main(int argc, char *argv[]){ 

    print(); 

    return EXIT_SUCCESS; 
} 

是否有這樣的編程風格的任何缺陷?雖然我感覺如此,但我無法弄清楚這個缺陷,因爲在某處我讀到將實現分隔爲* .h和* .c文件有助於編譯器檢查一致性。我不明白一致性意味着什麼。
我會非常感謝一些建議。

--thanks

+1

將代碼前綴爲4個空格(或在編輯器工具欄中選擇代碼按鈕)使其顯示爲代碼。你不需要代碼片斷反引號。 – 2009-06-20 14:29:15

回答

2

如果將數據與代碼分離起來更方便,將數據包含在另一個文件中並不罕見。例如,可以包含字符數組中的XPM或原始BMP數據,以這種方式在程序中嵌入圖像。如果數據是從另一個構建步驟生成的,那麼包含該文件是有意義的。

我建議使用不同的文件擴展名以避免混淆(例如* .inc,* .dat等)。

0

在你應該把函數原型的.h文件。例如,在你的代碼,你應該有:

//file.h 
void print(void); 

//file.c 
void 
print(void) 
{ 
    printf("Hello world\n"); 
} 
//file main.c 
#include <stdio.h> 
#include "file.h" 

int main(int argc, char *argv[]){ 

    print(); 

    return EXIT_SUCCESS; 
} 
+1

file1.c是一個例子,顯示了包含文件中有可執行代碼而不是正在使用的實際程序。 – 2009-06-20 14:38:41

6

你會遇到問題如果您在多個源代碼文件file.c這相結合,使庫/可執行文件,因爲你有重複的方法實現。上述情況讓我感到共享/重複使用代碼的可能性很低,不推薦使用。

9

沒有什麼能阻止你包含.c文件。然而,分離聲明(在.h文件)和實現(.c文件),然後只包括.h文件有以下幾個優點:

  • 編譯時間。你的聲明通常變化小於你的實現。如果只包含.h文件,並在實現中進行更改(在.c文件中),則只需重新編譯一個.c文件,而不是包含修改文件的所有文件。

  • 接口的可讀性和管理。所有的聲明都可以在(通常)很小的.h文件中查看,而.c文件則是用行和代碼行填充的。此外,它可以幫助您確定哪個文件查看哪些函數和變量。例如,爲了避免在不需要的地方包含全局變量。

9

這是一個普遍的期望,編譯器應該編譯.c文件。 .h文件不會直接提供給編譯器。它們通常只包含在.c文件中。

因此,你的代碼預計類似編譯:

gcc main.c file.c 

,而不是隻gcc main.c。該命令會在鏈接階段失敗,因爲它會看到重複的符號。

0

從C語言的角度來看,在程序中包含.c文件並沒有什麼錯誤。 C語言不關心文件的擴展,實際上C++通常會忽略某些頭文件的擴展以避免衝突。

但是從程序員的角度來看,這很奇怪。大多數程序員的操作假定不會包含.c文件,這可能會通過錯誤的假設導致問題。最好避免這種做法。如果你發現你必須使用它,這是一個設計不佳的標誌。

2

是的,這是允許的。

使用這是一個高級主題。

  • 它減慢了開發編譯時間(只需要編譯便宜)。
  • 它加快了部署編譯時間(所有文件都過期)。
  • 它允許編譯器跨模塊邊界內聯函數。
  • 它允許從庫中控制導出的符號,同時保持它的模塊化。
  • 它可能會混淆調試器。
0

只有兩個原因,我知道了,包括C文件(和意義):

  • 內聯函數,它們不平凡,但這是真正的風格
  • 份額實現方式的問題私人(靜態)功能通過在其他幾個文件中包含相同的文件。這實際上是做一個純粹的獨立於平臺的方式,只有這樣(但具體的工具鏈一樣的技巧隱藏屬性的GCC,等等......是,如果他們是可用的要好得多)

的缺陷:

  • 編譯幾次相同的代碼
  • 如果沒有節制地使用,它迅速導致多個定義的符號的公共符號,從某種意義上說這是難以調試(包括文件,其中包括其他文件...)
0

這是不好的風格,但另一個原因是它可以使用## token concatenation operator做一種窮人的模板在C中的一部分技巧。

請注意,這相當邪惡,isn' T建議的,並將產生的代碼很難調試和維護,但你可以類似如下:

mytemplate.c:

MyTemplateFunction_ ## MYTYPE(MYTYPE x) 
{ 
    // function code that works with all used TYPEs 
} 

的main.c:

#define MYTYPE float 
#include "mytemplate.c" 
#undef MYTYPE 

#define MYTYPE int 
#include "mytemplate.c" 
#undef MYTYPE 

int main(int, char*) 
{ 
    float f; 
    int i; 
    MyTemplateFunction_float(f); 
    MyTemplateFunction_int(i); 
    return 0; 
} 
0

宏的罪惡可以加劇:

file1.c中

#define bottom arse 

文件2。Ç

int f() 
{ 
    int arse = 4; 
    bottom = 3; 
    printf("%d", arse); 
} 

的main.c

#include "file1.c" 
#include "file2.c" 

void main() 
{ 
    f(); 
} 

事實上旋繞例子。但通常你不會注意到它,因爲宏的範圍就是它所在的文件。

我確實得到了這個錯誤,我正在將一些lib代碼導入到一個新項目中,並且無法編寫Makefile ,所以我只生成了一個包含庫中所有源的all.cpp。由於宏觀污染,它沒有按預期工作。花了我一段時間才弄明白。

0

這段長度的程序很好。