c - 需要一些关于 C header 包含的建议

标签 c compilation linker include c-preprocessor

简介

我是一名经验丰富的程序员,在面向对象范式方面拥有多年经验。最近我决定尝试更熟悉和熟悉比 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 获取单独的目标代码文件。

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

最佳答案

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

My question is though, is the linker clever enough to only put these declarations in the executable file once?

链接器当然不关心您包含什么头文件 - 它是链接器,而不是编译器。

So that even though I include these headers several places, it won't have any effect on file size and such?

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

And is this even the correct way of handling common dependencies between several source files?

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

对于您的项目,您应该这样做:

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 - 需要一些关于 C header 包含的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17981565/

相关文章:

android - 编译android框架

java - 由于缺少变量导致的编译器错误(变量在不同的类中定义)

c++ - 我可以向不同的线程发送信号吗

c - fork 返回的到底是什么?

java - 不清楚的编译时 Java 错误

linux - 有没有办法将 .rodata 段映射到不同的程序头中?

c++ - 如何在 OS X 上编译由谷歌的 protobuf 编译器生成的 C++ 文件

c - 结构末尾的填充物用于 future 增长

c - 这里的 `foo' 的地址会一直不为零吗?

c++ - 如何从链接器错误转到源代码中的代码行?