2013-11-01 33 views
6

我正在開始使用C編程。我目前有一個包含很多功能的大文件。我想將這些函數移動到一個單獨的文件中,以便代碼更易於閱讀。然而,我似乎無法弄清楚如何正確地包含/編譯,並且找不到我找到的任何在線教程中的示例。這裏有一個簡化的例子:如何將C函數移動到單獨的文件中?

#include <stdlib.h> 
#include <stdio.h> 

void func1(void) { 
    printf("Function 1!\n"); 
} 

void func2(void) { 
    printf("Function 2!\n"); 
} 

int main(void) { 
    func1(); 
    func2(); 
    return 0; 
} 

如何將C函數移動到單獨的文件中?僅供參考:我正在使用gcc。

更新:這些答案非常有幫助,謝謝。現在看來,我的簡化例子不夠好,因爲我意識到我的程序未能編譯的原因是因爲我在我的函數中使用了全局變量。

#include <stdlib.h> 
#include <stdio.h> 

int counter = 0; 

void func1(void) { 
    printf("Function 1!\n"); 
    counter++; 
} 

int main(void) { 
    func1(); 
    return 0; 
} 

移動這些功能到外部文件不起作用,因爲它們需要引用這個全局變量:

#include <stdlib.h> 
#include <stdio.h> 
#include "functions.c" 

int counter = 0; 

int main(void) { 
    func1(); 
    counter = 100; 
    return 0; 
} 

我怎樣才能解決這個問題得到什麼?

+0

只需將函數定義剪切並粘貼到另一個文件中,然後使用函數聲明創建一個頭部。您需要將此頭文件包含到使用'main()'的文件中。您現在需要編譯並鏈接每個源文件,編寫諸如'gcc -o program main.c functions.c'之類的東西。 – 2013-11-01 18:26:32

+2

請參閱:[在C中使用'.h'文件的好記錄模式是什麼?](http://stackoverflow.com/questions/256277)和[我應該在頭文件中使用'#include'嗎?]( http://stackoverflow.com/questions/1804486)獲取相關信息。 –

+0

謝謝@JonathanLeffler – Andrew

回答

4

首先您必須瞭解聲明定義之間的區別。一個聲明告訴編譯器存在一些東西,比如一個函數。就功能而言,定義是實際的功能實現。

所以你要做的是將定義移動到另一個文件,但是在函數被調用的文件中添加一個聲明。然後,您將這兩個文件一起構建,編譯器和鏈接器將負責其餘部分。

+1

*一個聲明告訴編譯器,像一個函數,exiSts * – smRaj

+0

@smRaj謝謝,修正。 – 2013-11-01 18:29:08

+0

謝謝,很高興知道這些條款。 – Andrew

0

你可以做這樣的事情。

/* func1.c */ 
    void func1(void) { 
     printf("Function 1!\n"); 
    } 

    /* func2.c */ 
    void func2(void) { 
     printf("Function 2!\n"); 
    } 

    /* main.c */ 
    #include "func1.c" 
    #include "func2.c" 

    int main (void) 
    { 
    func1(); 
    func2(); 
    return 0; 
    } 
+0

有趣...這也可以工作(不需要頭文件)。這是爲什麼? – Andrew

+1

-1:對不起,但是......包括'.c'源文件在某些​​情況下是可行的,但在大多數情況下不合理。 (它可以在這裏工作,但不能被推薦,即使它工作。)具體來說,如果你有兩個文件,'main.c'和'aux.c'(同一個程序的一部分),都需要使用'func1() '和'func2()',你不能在這兩個文件中使用這種技術。你需要一個頭文件來聲明至少在'main.c'和'aux.c'文件中使用的函數。當然,你應該有頭文件並將其包含在所有源文件('main.c','aux.c','func1.c'和'func2.c')中。 –

15

好的。開始了。

的main.c文件

#include <stdlib.h> 
#include <stdio.h> 
#include "functions.h" 

int main(void) { 
    func1(); 
    func2(); 
    return 0; 
} 

functions.h文件

void func1(void); 
void func2(void); 

functions.c文件

#include "functions.h" 

void func1(void) { 
     printf("Function 1!\n"); 
    } 

    void func2(void) { 
     printf("Function 2!\n"); 
    } 

與編譯:

gcc -o main.exe main.c functions.c 
+0

感謝您的完整示例。似乎創建一個頭文件是不必要的,如果我只能'#include「functions.c」'。爲什麼我會創建一個頭文件? – Andrew

+0

你會創建頭,因爲通常你有多個使用函數的源文件(所以'main.c'也有'aux.c'和...),它們不能全部使用#include「func1.c」技巧;只有一個源文件可以做到這一點,但其他的仍然需要函數聲明,所以你需要一個頭文件。 –

+1

是的。但是,這是一個包含頭文件的好習慣,這樣你的全局聲明就可以完成,代碼看起來不錯。人們也同意Jonathan Leffler的觀點。 –

6

最常用的方法是將一個頭文件中的函數原型和你的函數實現的源文件。例如:

func1.h

#ifndef MY_FUNC1_H 
#define MY_FUNC1_H 
#include <stdio.h> 

// declares a variable 
extern int var1; 

// declares a function 
void func1(void); 
#endif 

func1.c

#include "func1.h" 

// defines a variable 
int var1 = 512; 

// defines a function 
void func1(void) { 
    printf("Function 1!\n"); 
} 

FUNC2。H:

#ifndef MY_FUNC2_H 
#define MY_FUNC2_H 
#include <stdio.h> 
void func2(void); 
#endif 

func2.c:

#include "func1.h" // included in order to use var1 
#include "func2.h" 
void func2(void) { 
    printf("Function 2 with var1 == %i\n", var1); 
} 

的main.c:

#include <stdio.h> 
#include "func1.h" 
#include "func2.h" 

int main(void) { 
    var1 += 512; 
    func1(); 
    func2(); 
    return 0; 
} 

你可以這樣編譯使用如下:

gcc -c -o func1.o func1.c 
gcc -c -o func2.o func2.c 
gcc -c -o main.o main.c 
gcc -o myprog main.o func1.o func2.o 
./myprog 

我只放在一個在每個源/頭對中用於說明。您只能創建一個包含所有源文件原型的頭文件,或者可以爲每個源文件創建多個頭文件。關鍵是任何將調用函數的源文件都需要包含一個包含該函數原型的頭文件。

作爲一般規則,您只需要一次包含頭文件,這是頭文件中的#ifndef #define #endif宏的用途。

+0

謝謝!我添加了一個提到全局變量的更新。我將如何處理這些? – Andrew

+0

我已經更新了示例以使用共享的'int'變量。 –

+0

請注意,'func1.h'和'func2.h'都不需要包含''來使文件中的聲明編譯,因此應該省略嵌套的include。標題應該是冪等的(就像你的標題守衛一樣)並且是獨立的。你的設備也是獨立的,但是它們包括不合理的標題。請參閱[我應該在頭文件中包含嗎?](http://stackoverflow.com/questions/1804486) –

相關問題