2013-07-31 187 views
3

介紹需要在C頭包含

一些建議,我是一個有經驗的程序員,並有多年的面向對象的範式經驗。最近我決定嘗試使用比C#或Java等語言稍低一些的語言來熟悉和習慣,因此我正在鑽研C,並嘗試用它創建一些遊戲。

一切都非常好,現在我試圖整理我的代碼通過移動功能定義爲獨立的.c文件更好。由於納入C,我開始感到不舒服。我對它的工作原理以及編譯過程中的預處理階段非常熟悉。問題是我仍然不確定我是否正確處理這個問題。

我想我的問題類似於什麼已要求here。雖然它沒有完全滿足我需要知道的東西。

的問題

本質上講,我創建一個使用兩個庫一個OpenGL項目。一個是GLEW(對OpenGL函數加載),另一種是GLFW(畫面處理和OpenGL上下文創建)。我有兩個.c文件,一個叫main.c中和另一個叫windowInitialize.c。問題是,無論是main.c中windowInitialize.c依賴於GLEW和GLFW庫。

在我的main.c文件我這樣做,包括:

#include "includes/GLEW/glew.h" 
#include "includes/GLFW/glfw3.h" 
#include "windowInitialize.h" 

此外,的main.c執行以下操作相關的函數調用:

if (!initializeGLFW()) 
return -1; 

GLFWwindow *window = createOpenGLWindow(3, 3, 640, 480, "Hello OpenGL"); 

/* It is important that we initialize glew AFTER initializing GLFW and setting up 
the OpenGL context, as GLEW needs a current context to work */ 
initializeGLEW(); 

windowInitialize.c包括函數的定義初始化GLFWinitializeGLEW,以及createOpenGLWindow。儘管爲了主循環目的,源仍然使用glfw,其中涉及來自兩者的功能等。

現在,windowInitialize.c做這些包括:

#include "windowInitialize.h" 
#include "includes/GLEW/glew.h" 
#include "includes/GLFW/glfw3.h" 
#include <stdio.h> 

此後進入填寫函數定義。這就是交易。這兩個文件都需要使用,如果glew和glfw庫,以及stdio實際(用於打印調試消息等)。

我覺得這是不這樣做的正確的方式,但我不知道。我相信編譯器/鏈接器不抱怨雙聲明的原因是因爲main.c和windowInitialize.c獲取單獨的對象代碼文件。

我的問題是,雖然鏈接器足夠聰明,只將這些聲明放在可執行文件中一次?因此,即使我將這些頭文件包含在幾個地方,它不會對文件大小產生任何影響,並且這樣做?這甚至是處理幾個源文件之間常見依賴關係的正確方法嗎?或者我應該使用另一種方法?

回答

6

你所描述的一切似乎都是正常的做事方式。您的兩個編譯單元僅在這些頭文件中獲得相同的前向聲明函數,而不是庫中的實際重複定義。

我的問題是,雖然鏈接器足夠聰明,只將這些聲明放在可執行文件中一次?

鏈接器當然不關心你包含的頭文件 - 它是一個鏈接器,而不是編譯器。

所以,即使我有這些頭幾個地方,它不會對文件大小和這樣有什麼影響?功能

超/未使用前置聲明將會對二進制文件的大小沒有任何影響。

這是甚至正確的方式來處理幾個源文件之間的常見依賴關係嗎?

是的,你似乎在以完全正常的方式做事。

爲你的項目,你應該做的是這樣的:

cc -c -o main.o main.c       # compile main.c 
cc -c -o windowInitialize.o windowInitialize.c # compile windowInitialize.c 
cc -o myProgram main.o windowInitialize.o -lglew -lglfw # link objects with necessary libraries to create executable 

但是,真的,使用的makefile會更好:

myProgram: main.o windowInitialize.o 
    cc -o [email protected] $^ -lglew -lglfw 

例使用它的:

$ make 
cc -c -o main.o main.c 
cc -c -o windowInitialize.o windowInitialize.c 
cc -o myProgram main.o windowInitialize.o -lglew -lglfw 
+0

謝謝你非常明確的答案和額外的例子:)非常感謝!對於我的純C項目,我使用CodeBlocks和MinGW。當我編譯該項目時,我可以在日誌中看到CodeBlocks使用的編譯方法與您的示例非常相似,僅在標記爲:)的某些附加選項上 – CodingBeagle

1

鏈接器將只使用您實際使用的庫中的那些函數,並且它只執行一次。至於這種方法,在本書中,我正在閱讀atm建議,就是要創建一個包含所有庫,函數聲明和定義的文件,並僅包含一個名爲eg的文件。 mydefinitions.h,而不是在您的項目的每個單獨文件中單獨執行。希望能幫助到你。