C文字常量:在标题或C文件中?

时间:2012-08-09 12:59:16

标签: c header const

我想在na单个静态C程序中包含一堆数据(比如图像,还有其他数据,嵌入在可执行文件中,因为我在没有文件的嵌入式平台上工作)。

因此,我写了一些img2c从我的数据文件创建const数据,创建一个带有静态const数组初始化器的文件放到flash中(使用C99漂亮的功能)

我的问题是,我应该将它们放在.h文件中,就像我多次看到的那样 - 例如gimp可以保存为.h文件,而不是.c文件 - 或者在.c文件中,在标题只有const extern声明进一步引用,不必包含所有数据并将其全部传递给编译器,并在每次使用时重新声明它?

预处理器宏是不可能的,因为我将引用它们的地址,而不是每次都包含整个数据。

4 个答案:

答案 0 :(得分:4)

如果您将数据放入标题中,那么每个编译单元都会获取该标题将获得自己的数据副本。想象一下两个.c文件,每个文件都转到.o。每个.o都有一份数据副本,你的最终可执行文件可能比它需要的大。

如果你把它放在一个.c中并在一个标题中extern它,只有一个.o将包含数据,你的最终可执行文件可以更小。此外,如果您更改了内容,则重新编译可能会更快,如果它只是对单个.c的更改而不是包含您的标头的所有.c文件。

如您所述,您可能也会遇到链接器问题,因为符号将被多次定义,请参阅Repeated Multiple Definition Errors from including same header in multiple cpps的答案。将标题中的extern和.c

中的数据放在一起会更好

答案 1 :(得分:2)

与C中的所有内容一样,这里有一些关于最佳实践的争论。 Common 实践是将实际值(.c)和声明(extern something something)放在标题(.h)中。这样,您可以更新值,而无需重新编译包含标题的每个文件。

答案几乎从不“每次使用它时重新声明它。”

答案 2 :(得分:2)

这可以通过确保变量仅在单个源文件中定义来完成。为此,需要一些预处理器“编程”。

标题文件:

/* Standard include guard */
#ifndef X_H
#define X_H

#ifdef X_SOURCE
uint8_t data[] = { /* ... */ };
#else
extern uint8_t data[];
#endif

#endif  /* End of include guard */

源文件:

#define X_SOURCE
#include "x.h"

/* ... */

所有其他源文件只需要包含文件"x.h",他们就可以引用data

答案 3 :(得分:2)

C中的头文件没什么特别的; .h扩展名不会改变编译器处理它们的方式。这更像是对人类的暗示“这个文件可能不包含任何代码”。

因此,如果您将实际的二进制数据放在那里,编译器将在每个包含标题的文件中创建数组的副本(而不是简单地添加对共享全局数组的引用)。

GIMP会创建一个头文件,因为它不知道您打算如何使用这些数据。我们的想法是,您只需在.c文件中包含此头文件一次,然后以某种方式处理数据。如果它写了一个.c文件并且您对代码进行了更改,那么当您要求更新数据时,GIMP必须合并这些更改 - 它会很混乱。