【问题标题】:C literal constants : in header or C file?C 文字常量:在头文件或 C 文件中?
【发布时间】:2012-08-06 17:08:25
【问题描述】:

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

因此,我编写了一个小 img2c,从我的数据文件创建 const 数据,创建一个带有静态 const 数组初始化器的文件以放入闪存(使用 C99 的优秀功能)

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

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

【问题讨论】:

  • 顺便说一句,GIMP 可以保存到 C 源文件以及头文件。它在 File->Save As 下并将文件类型更改为 C 源代码。
  • 是的,当然。我的评论更多的是,默认情况下,它保存到 .h 这似乎违反直觉。

标签: c header constants


【解决方案1】:

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

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

正如您所指出的,您也可能会遇到链接器问题,因为符号将被定义多次,请参阅Repeated Multiple Definition Errors from including same header in multiple cpps 的答案。将 extern 放在 header 中并将数据放在 .c 中会更好

【讨论】:

  • 链接步骤不会去掉副本吗?
  • @Eregrith,不,不具备标准 C 功能。为此,您必须使它们成为“弱”符号。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    头文件:

    /* 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

    【讨论】:

    • 虽然这可行,但有一个缺点:如果数组很大,至少预处理器必须解析它 -> 它会减慢编译器的速度。
    • @AaronDigulla,我可以向你保证,这些天预处理器的性能几乎从来都不是问题。这里是#if 条件句中的代码。在查看# 的第一个非空白字符时,这些行可以(并且是!)略过。
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多