// common.h
// This is foo function. It has a body.
__inline void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
我想在我为发布版本构建时内联 foo 函数。我不想为Debug
构建内联函数。
我试过了,但链接器错误让我感到恼火
在这种情况下,foo
函数的主体在 common.h 头文件中定义
所以,如果我只是做
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
DEBUG
版本中会遇到链接错误。因为两个模块试图包含common.h
我不知道要解决它。
有可能吗?
答案 0 :(得分:7)
“简单”解决方案就是:
#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
static
对于消除链接错误和绕过单一定义规则是必要的。
更好的解决方案是简单地禁用内联项目进行调试。 GCC支持-wno-inline-functions
和-fno-inline-small-functions
选项来抵消这些优化,并且不启用-O1
或更低版本(可能-Os
以及)。大多数编译器都有类似的选项。
我将后者称为更好的解决方案,因为它应该指示编译器忽略inline
提示,从而无需使用讨厌的预处理程序指令。
答案 1 :(得分:5)
要实现的基本要点是,inline
关键字(或Microsoft的__inline
扩展名为C - 因为MSVC不支持C99)本质上是违反一个定义规则的过程。如果你考虑一下 - 这就是它的全部,因为编译器没有义务实际执行任何内联。
因此,当您拥有inline
函数时,您可以在多个模块中定义函数。事实上,您有义务在任何实际使用该功能的模块中定义它。
但是,如果您没有将该函数声明为inline
,则必须确保您只有一个定义(如果它实际被使用,则只有一个)。对于非成员函数(C中的所有函数),有几种方法:
static
以更改它与内部的链接(请注意,您可以开始使用static inline
函数)。基本上,你需要做的是在一个单独的.c文件中实现该函数,就像你遵循传统的单模函数编码标准(实际上你可以这样做)同样在.c模块中放置几个内联函数 - 但是它们都应该是内联的或不是内联的,以防止事情变得太失控。该函数的实现需要安排能够包含在标题中 - 因此它需要包括警卫,就像任何其他标题一样。然后,当您需要内联函数时,使用预处理器有条件地将实现作为标题的一部分包含在内(因此实现将可用于所有模块),但如果您没有内联,则不要包含它(因此,请遵循一个在那种情况下的定义规则):
common.h
标题:
// common.h
#ifndef COMMON_H
#define COMMON_H
#ifdef RELEASE
#define USE_INLINE
#define INLINE __inline
#else
#define INLINE
#endif
INLINE void foo(void);
#ifdef USE_INLINE
#include "foo.c"
#endif
#endif /* COMMON_H */
foo()
的实施:
// foo.c
#ifndef FOO_C
#define FOO_C
#include <stdio.h>
#include "common.h"
INLINE void foo()
{
printf("foo\n");
}
#endif /* FOO_C */
一个示例程序:
// main.c
#include<stdio.h>
#include "common.h"
int main()
{
foo();
return 0;
}
现在,如果你为发布版编译:
cl /DRELEASE main.c foo.c
foo()
将为inline
(或__inline
视情况而定)。
如果编译为非发行版:
cl test.c foo.c
您有非内联foo()
。
无论是哪种情况,编译器和链接器都都很满意。
所有这一切,我都喜欢将INLINE
重新定义为static
以进行调试的建议。
然而,最终我不确定我是否真的看到了这一点 - 现代调试器能够逐步执行inline
的函数,如果禁用调试器可能不会内联函数调用优化。因此,您也可以在内联函数中设置断点,并使其在非优化构建中正常工作。
我真的不确定你到底是什么目标。将函数inline
保留在调试/非优化构建中有什么缺点?
答案 2 :(得分:4)
#ifdef RELEASE
#define INLINE __inline
#else
#define INLINE
#endif
然后
// common.h
INLINE void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
然后为发布版本定义RELEASE
。当然,你可以从中看到有很多方法可以做到。
答案 3 :(得分:3)
您不能将仅标题函数声明为非内联函数。您可以将它们声明为静态(a.k.a. C风格静态),但这将在每个转换单元中生成函数的副本(包括本地静态变量,如果有的话)。更好的解决方案是将其保留为内联。在调试模式下,当禁用优化时,编译器通常不会内联任何函数。
答案 4 :(得分:1)
在大多数情况下,未定义发布标志。通常定义调试标志。 _DEBUG由大多数编译器定义,因此无需定义发布标志:
更实用:
#ifndef _DEBUG
__inline void foo() { /* something */ }
#else
//some alternative
#endif
答案 5 :(得分:0)
使用编译器条件并定义编译时标志。
示例:强>
#ifdef RELEASE_BUILD_FLAG
//Run inline function
#else
//some alternative
#endif