【问题标题】:Need some advice on C header inclusion需要一些关于 C 标头包含的建议
【发布时间】:2013-08-01 15:19:49
【问题描述】:

简介

我是一位经验丰富的程序员,在面向对象范式方面拥有多年经验。最近我决定尝试更熟悉和更熟悉比 C# 或 Java 等语言级别低一些的语言,所以我正在深入研究 C,并将尝试创建一些游戏用它。

一切进展顺利,现在我正试图通过将函数定义移动到单独的 .c 文件中来更好地组织我的代码。由于包含在 C 中的性质,这就是我开始感到不舒服的地方。我非常熟悉它的工作原理,以及编译期间的预处理阶段。问题是我仍然不确定我是否正确处理了这个问题。

我认为我的问题类似于here 提出的问题。虽然它并没有完全满足我需要知道的。

问题

基本上,我正在使用两个库创建一个 OpenGL 项目。一个是glew(用于OpenGL函数加载),另一个是GLFW(用于窗口处理和OpenGL上下文创建)。我有两个 .c 文件,一个名为 main.c,另一个名为 windowInitialize.c。问题是,main.cwindowInitialize.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 包括函数initializeGLFWinitializeGLEW 以及createOpenGLWindow 的定义。 main.c 源代码仍然使用 glewglfw 用于主循环目的,从两者中引用函数等。

现在,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 获得了单独的目标代码文件。

我的问题是,链接器是否足够聪明,只将这些声明放在可执行文件中一次?所以即使我在几个地方包含这些标题,它不会对文件大小等产生任何影响?这甚至是处理多个源文件之间常见依赖关系的正确方法吗?还是应该使用其他方法?

【问题讨论】:

    标签: c compilation linker include c-preprocessor


    【解决方案1】:

    你所描述的一切似乎都是正常的做事方式。您的两个编译单元仅在这些标头中获得相同的前向声明函数,而不是来自库的实际重复定义。

    我的问题是,链接器是否足够聪明,只将这些声明放在可执行文件中一次?

    链接器当然不关心你包含什么头文件——它是一个链接器,而不是一个编译器。

    所以即使我在几个地方包含这些标题,它也不会对文件大小等产生任何影响?

    额外/未使用的函数前向声明对二进制大小没有影响。

    这甚至是处理多个源文件之间常见依赖关系的正确方法吗?

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

    对于您的项目,您应该执行以下操作:

    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
    

    【讨论】:

    • 感谢您提供非常明确的答案和其他示例 :) 非常感谢!对于我的纯 C 项目,我将 CodeBlocks 与 MinGW 一起使用。当我编译项目时,我实际上可以在日志中看到 CodeBlocks 使用的编译方法与您的示例非常相似,只是在上面标记了一些附加选项:)
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多