需要一些关于C头包含的建议

时间:2013-07-31 21:47:14

标签: c compilation linker include c-preprocessor

简介

我是一名经验丰富的程序员,拥有多年的面向对象范式经验。最近我决定尝试使用比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 包括函数 initializeGLFW initializeGLEW 的定义,以及 createOpenGLWindow main.c 源仍然使用 glew 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获取了单独的目标代码文件。

我的问题是,链接器是否足够巧妙,只能将这些声明放在可执行文件中一次?即使我将这些标题包括在几个地方,它也不会对文件大小产生任何影响吗?这甚至是处理几个源文件之间的公共依赖关系的正确方法吗?或者我应该使用其他方法吗?

2 个答案:

答案 0 :(得分: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 $@ $^ -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

答案 1 :(得分:1)

链接器将仅使用您实际使用的库中的那些函数,它只执行一次。至于方法,在书中我正在阅读atm建议是制作一个包含所有库,函数声明,定义的文件,并且只包含一个文件,例如。 mydefinitions.h,而不是在项目的每个文件中单独执行。希望它有所帮助。