2013-07-31 132 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,而不是在您的项目的每个单独文件中单独执行。希望能帮助到你。