【问题标题】:Correct C header structure正确的 C 头文件结构
【发布时间】:2011-11-29 14:35:54
【问题描述】:

构造标题的正确方法是什么?有一些类似的问题,但没有一个给出好的答案。现在我正在使用这个:

#ifndef INCLUDE_FILENAME
#define INCLUDE FILENAME

/* Includes */

/* Constants, enums */

/* Structure */

/* Globals */

/* Function prototypes */

#include "File.c"

#endif

然后我#include来自程序的标题。

这有很多问题,必须以正确的顺序包含内容,我相当确定这是错误的结构。

理想情况下,它应该在构建单个文件和单独构建模块时工作。

一个相关的问题是:全局变量应该在头文件中实现,还是定义为外部并在源文件中实现?

【问题讨论】:

  • 为什么将宏 INCLUDE 定义为 FILENAME? :)
  • 您实际上是否在头文件中包含源文件,如您的示例所示?这通常是不受欢迎的,因为它可能导致多个定义问题。
  • Nobody & Nate 一针见血。
  • 我假设你的意思是#define INCLUDE_FILENAME?
  • @Bart 和 @Nobody,对不起:是的,这是一个错字。

标签: c module header


【解决方案1】:

理想情况下,头文件不应定义任何数据或代码。这意味着全局变量应该只在标头中声明,然后在源文件中定义

头文件的目的是为编译器提供提示,而不是包含实际的数据和代码。

此外,源文件根本不应该包含在内,每个源文件通常直接传递给编译器。

【讨论】:

  • 澄清似乎确实是初学者的OP:使用extern关键字在头文件中声明了一个变量。它通过重复相同的声明但省略extern 关键字在相应的源文件中定义。 (虽然,全局变量的使用是相当有争议的)
  • 要声明但不定义全局变量,请将“extern”关键字放在它前面。这对编译器说“在另一个编译单元中有一个具有此名称的这种类型的符号”。或者更好的是,将对全局变量的直接访问限制在定义它的编译单元中。使用函数调用从其他单元访问它。
  • @AdrienPlisson:比我快 20 秒。
  • @AdrienPlisson,在这种情况下,全局变量通常是字符串表或类似的。我已经编程了足够长的时间,知道何时以及何时不使用全局变量,它是 C 和它的怪癖对我来说是新的。
  • @Jerry:此示例程序在使用 GCC 编译时会产生“未定义的测试引用”错误。 extern int test; int main(int argc, char **argv) { return test; } 请提供extern type name 作为定义的示例。
【解决方案2】:

例如,我不喜欢这种方法,我的解决方案不可移植,但我不打算将其移植到任何其他平台。 我正在使用#pragma once IAR 编译器扩展,这会导致编译器只包含此文件一次,无论包含多少次。

这是一个取自维基百科的例子,它是如何使用的:

#pragma once

struct foo 
{
    int member;
};

代替:

#ifndef GRANDFATHER_H
#define GRANDFATHER_H

struct foo
{
    int member;
};

#endif /* GRANDFATHER_H */

我认为这是更清洁的方法...

根据Wikipedia,该指令也支持 Clang,Comeau C/C++,Digital Mars C++,GCC,Intel C++ 编译器,Microsoft Visual Studio 所以在实践中它非常便携...... :)

【讨论】:

  • 第二个示例中的#pragma once 是错误还是我对这种模式有误解?
【解决方案3】:

这是一个口味问题,您应该只确保在使用之前声明或前向声明事物,这取决于您的代码。

而且您通常不会在标题中包含 #include .c

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-10
    • 2023-01-10
    • 2018-01-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多