我们为什么不应该将定义放在标头中? [英] Why should not we put definition to headers?

查看:79
本文介绍了我们为什么不应该将定义放在标头中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我一个人仍然无法回答的问题(可能是由于缺乏C方面的经验).

This is the question I still cannot answer by myself (probably due to lack of experience in C).

所以我找到了这个答案,问题是将定义放入头文件有什么问题?我不声明它们为静态,这应该没问题,因为它们将具有外部链接,并且链接程序也不会抱怨.

So I found this answer and the question is what's wrong with putting definitions into a header files? I we don't declare them as static it should be fine since they will have external linkage and linker will not complain.

第二,为什么我们不应该将static定义放入头文件中?假设我们要使某种编译单元私有"的功能类型不打算具有外部链接.

Secondly, why should not we put static definition into a header file? Suppose we want to make some function sort of "compilation-unit private" that is not intended to have external linkage.

令我惊讶的是,为什么(很少)有可能将inline函数定义放入头文件中?

And what I was surprised about was why is it (rarely) possible to put inline function definition into header files?

仅是按照惯例吗?

推荐答案

通常除非将信息包含在多个其他源文件中,否则将信息放入标头通常没有任何意义.这意味着,如果标头定义了一些变量,则包含标头的每个源文件都将定义这些变量.通常,多次定义同一(全局)变量是一个错误.因此,将变量定义放在标头中通常可以消除首先创建标头的原因.

There is not usually any point in putting information into a header unless it will be included in multiple other source files. That means that if the header defines some variables, each source file that includes the header will define those variables. And it is normally an error to define the same (global) variable more than once. So, putting variable definitions into a header normally defeats the reason for creating a header in the first place.

请注意,C确实有一个单一定义规则",类似于C ++,但没有那么强.有一个通用"扩展名(附有双句号),通常可以让您摆脱在多个文件中定义变量的麻烦,但是如果该变量具有非平凡的初始化,它将无法正常工作.

Note that C does have a 'one definition rule', similar to C++, but not as strong. There is a 'common' extension — complete with double entendre — that often allows you to get away with defining a variable in more than one file, but it doesn't work if the variable has a non-trivial initialization.

您可以在

You can find a lot of information in How do I use extern to share variables between source files?, including information about the common extension.

通常不应在标头中定义静态变量,因为这意味着每个包含标头的文件都将定义自己的变量副本.这通常不是想要的.它倾向于使程序更大.

You should not normally define static variables in a header because that means that each file that includes the header will define its own copy of the variables. This is usually not what's wanted. It tends to make programs bigger.

如果您可靠地使用支持inline的编译器,则没有特殊原因不能将static inline函数定义放入标头中.如果无法内联函数,则存在风险,编译器将在使用该函数的每个源文件的目标代码中生成静态函数,从而再次增大了可执行文件的大小.您可以通过使用非静态inline函数定义来避免这种情况.如果函数足够小以至于可以内联,则没有特别的理由不将它们放在标头中.

If you reliably work with compilers that support inline, there is no particular reason why you can't put static inline function definitions into a header. There is a risk that if the function cannot be inlined, then the compiler will generate a static function in the object code for each source file that uses the function, again increasing the size of the executable. You might be able to avoid that by using non-static inline function definitions. If the functions are small enough that they will be inlined, there is no particular reason not to put them in a header.

您可以在堆栈溢出的问答中找到有关inline函数的更多信息,并使用staticextern:

You can find more information about inline functions, with static or extern, in the Q&A on Stack Overflow:

  • extern inline
  • Is inline without static or extern ever useful in C99
  • What's the difference between static and static inline functions?

请注意,以上答案中诸如通常"和通常"之类的狡猾的单词被大量使用.您可以小心地找到需要打破规则的特殊情况,但是如果您还记得标头是在使用某些功能(类型,常量,函数,有时是变量)的代码与使用某些功能的代码之间进行交叉检查的粘合剂实现功能,那么您将意识到遵循以下规则是很好的:

Note the rather extensive use of weasel words such as 'usually' and 'normally' in the answer above. You can, with care, find exceptional situations that warrant breaking the rules, but if you remember that headers are the glue that provide cross-checking between the code that uses some functionality (types, constants, functions, sometimes variables) and the code that implements the functionality, then you'll realize that it is good to follow these rules:

  • 标头声明了多个源文件使用的类型,常量,枚举,函数,变量.
  • 源文件实现功能并定义多个源文件使用的变量.
  • 实现代码使用头文件来确保实现与规范匹配.
  • 使用者代码使用头文件来遵循实现的源代码级规则.
  • 头文件不应定义变量.
  • 源文件不应声明外部变量;它们应包含相关的标题.
  • 标题可以合理地定义static inline函数;您甚至可以在标头中包含普通的inline函数定义,但是您必须小心地在某处实例化这些函数,以防它们未内联—这就是extern inline起作用的时候. (请注意,inline函数的旧GCC规则与C99标准规则不同.)
  • Headers declare types, constants, enumerations, functions, variables that are used by multiple source files.
  • Source files implement functions and define variables that are used by multiple source files.
  • The header files are used by the implementation code to ensure that the implementation matches the specification.
  • The header files are used by the consumer code to follow the source-level rules for the implementation.
  • Header files should not define variables.
  • Source files should not declare external variables; they should include the relevant header.
  • Headers may sensibly define static inline functions; you may even include plain inline function definitions in a header, but you have to be careful to instantiate the functions somewhere in case they are not inlined — and that's when extern inline comes into play. (Be aware that old GCC rules for inline functions are different from C99 standard rules.)

有些规则仅包含标头就不会强制执行,例如调用函数所需的顺序(例如,不要在相应的分配函数之前调用自由函数).但是明智地使用标头可以避免很多错误.

There are some rules that simply including a header won't enforce, such as required sequences for calling functions (don't call a free function before the corresponding allocate function, for example). But using headers wisely prevents a lot of errors.

另请参阅:

  • Should I use #include in headers?
  • How to link multiple implementation files in C?

毫无疑问还有许多其他问题.

And many other questions, no doubt.

这篇关于我们为什么不应该将定义放在标头中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆