简体   繁体   English

仅标题链接

[英]Header-only linking

Many C++ projects (eg many Boost libraries) are "header-only linked". 许多C ++项目(例如许多Boost库)都是“仅限标题链接”。

Is this possible also in plain C ? 这在普通C也可能吗? How to put the source code into headers? 如何将源代码放入标题? Are there any sites about it? 有没有关于它的网站?

Executive summary: You can, but you shouldn't. 执行摘要:你可以,但你不应该。

C and C++ code is preprocessed before it's compiled: all headers are "pasted" into the source files that include them, recursively. C和C ++代码在编译之前进行预处理 :所有标题都以递归方式“粘贴”到包含它们的源文件中。 If you define a function in a header and it is included by two C files, you will end up with two copies in each object file ( One Definition Rule violation). 如果在标题中定义一个函数并且它包含在两个C文件中,则每个目标文件最终会有两个副本( 一个定义规则违规)。

You can create "header-only" C libraries if all your functions are marked as static , that is, not visible outside the translation unit. 如果所有函数都标记为static ,即在翻译单元外部不可见,则可以创建“仅标题”C库。 But it also means you will get a copy of all the static functions in each translation unit that includes the header file. 但这也意味着您将获得包含头文件的每个翻译单元中所有静态函数的副本。

It is a bit different in C++: inline functions are not static , symbols emitted by the compiler are still visible by the linker, but the linker can discard duplicates, rather than giving up ("weak" symbols). 它在C ++中有点不同:内联函数不是static ,编译器发出的符号仍然可以被链接器看到,但链接器可以丢弃重复,而不是放弃(“弱”符号)。

It's not idiomatic to write C code in the headers, unless it's based on macros (eg queue(3) ). 在头文件中编写C代码并不是惯用的,除非它基于宏(例如queue(3) )。 In C++, the main reason to keep code in the headers are templates, which may result in code instantiation for different template parameters, which is not applicable to C. 在C ++中,将代码保留在头文件中的主要原因是模板,这可能导致不同模板参数的代码实例化,这不适用于C.

You do not link headers. 您没有链接标题。

In C++ it's slightly easier to write code that's already better-off in headers than in separately-compiled modules because templates require it. 在C ++中,编写已经在头文件中比在单独编译的模块中更好的代码要容易一些,因为模板需要它。 1 1

But you can also use the inline keyword for functions, which exists in C as well as C++. 但是你也可以使用inline关键字作为函数,它存在于C和C ++中。 2 2

// Won't cause redefinition link errors, because of 6.7.4/5
inline void foo(void) {
   // ...
}

[c99: 6.7.4/5:] A function declared with an inline function specifier is an inline function . [c99: 6.7.4/5:]使用inline函数说明符声明的函数是内联函数 The function specifier may appear more than once; 函数说明符可能出现多次; the behavior is the same as if it appeared only once. 行为与它只出现一次的行为相同。 Making a function an inline function suggests that calls to the function be as fast as possible. 使函数成为内联函数表明对函数的调用尽可能快。 The extent to which such suggestions are effective is implementation-defined. 这些建议有效的程度是实施定义的。

You're a bit stuck when it comes to data objects, though. 但是,当谈到数据对象时,你会有点卡住。


1 - Sort of. 1 - 排序。
2 - C99 for sure. 2 - C99肯定。 C89/C90 I'd have to check. C89 / C90我得检查一下。

Boost makes heavy use templates and template meta-programming which you cannot emulate (all that easily) in C. Boost使用大量使用模板和模板元编程,你无法在C中模拟(很容易)。

But you can of course cheat by having declarations and code in C headers which you #include but that is not the same thing. 但是你当然可以通过在C #include头中使用声明和代码来作弊,但这不是同一件事。 I'd say "When in Rome..." and program C as per C conventions with libraries. 我会说“什么时候在罗马......”并根据C约定使用库编写C程序。

Yes, it is quite possible. 是的,很有可能。 Declare all functions in headers and either all as static or just use a single compilation unit (ie only a single c file) in your projects. 在头文件中声明所有函数,或者全部作为static函数,或者只在项目中使用单个编译单元(即只有一个c文件)。

As a personal anecdote, I know quite a number of physicists who insist that this technique is the only true way to program C. It is beneficial because it's the poor man's version of -fwhole-program , ie makes optimizations based on the knowledge of function behaviour possible. 作为个人轶事,我知道很多物理学家坚持认为这种技术是编程C的唯一真正方法。这是有益的,因为它是穷人的-fwhole-program版本,即根据功能知识进行优化行为可能。 It is practical because you don't need to learn about using the linker flags. 这很实用,因为您不需要了解使用链接器标志。 It is a bad idea because your whole program must be compiled as a whole and recompiled with each minor change. 这是一个坏主意,因为您的整个程序必须作为一个整体进行编译,并在每次微小更改时重新编译。

Personally, I'd recommend to let it be or at least go with static for only a few functions. 就个人而言,我建议让它成为或至少使用static只为少数功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM