C 如何内联仅用于发布版本的函数
我只想在为发布版构建时内联foo函数。我不想为C 如何内联仅用于发布版本的函数,c,function,inline,c-preprocessor,C,Function,Inline,C Preprocessor,我只想在为发布版构建时内联foo函数。我不想为Debugbuild内联函数 我试过了,但链接器错误让我很恼火。 在这种情况下,foo函数的主体在common.h头文件中定义。 所以如果我这么做的话 // common.h // This is foo function. It has a body. __inline void foo() { /* something */ } // a.cpp #include "common.h" // for foo function // Call f
Debug
build内联函数
我试过了,但链接器错误让我很恼火。在这种情况下,
foo
函数的主体在common.h头文件中定义。所以如果我这么做的话
// 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
在DEBUG
build中会遇到链接错误。因为两个模块试图包含common.h.我没有办法解决它。
可能吗?使用编译器条件并定义编译时标志 示例:
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
然后
然后为发布版本定义
RELEASE
。当然,您可以从中看到有很多方法可以做到这一点。在大多数情况下,没有定义发布标志。通常会定义调试标志。
_调试由大多数编译器定义,因此无需定义发布标志:
更实用:
// 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
“简单”的解决方案是:
#ifndef _DEBUG
__inline void foo() { /* something */ }
#else
//some alternative
#endif
static
是消除链接错误和绕过一个定义规则所必需的
更好的解决方案是简单地禁用项目范围内的内联以进行调试。GCC支持-wno内联函数
和-fno内联小函数
选项来抵消这些优化,并且它也不为-O1
或更低版本(也可能是-Os
启用内联)。大多数编译器都有类似的选项
我称后者为更好的解决方案,因为它应该指示编译器忽略
inline
提示,从而消除讨厌的预处理器指令的需要。您不能将仅头函数声明为非内联函数。您可以将它们声明为静态(也称为C风格的静态),但这将在每个转换单元中生成函数的副本(包括局部静态变量,如果有的话)。更好的解决方案是将其保留为内联。在调试模式下,当禁用优化时,编译器通常不会内联任何函数。需要了解的基本情况是,内联
关键字(或Microsoft的\u内联
C扩展-因为MSVC不支持C99)本质上是违反一个定义规则的过程。如果你仔细想想,这就是它真正的意义所在,因为编译器没有义务实际执行任何内联
因此,当您有一个内联
函数时,您可以在多个模块中定义该函数。事实上,您有义务在实际使用该函数的任何模块中定义它
但是,如果不将函数声明为内联
,则必须确保定义不超过一个(如果实际使用,则正好是一个)。对于非成员函数(C中的所有函数),有几种解决方法:
- 将函数声明为
以将其链接更改为internal(请注意,您可以先使用static
函数)static inline
- 在C++中,可以将它们放置在匿名命名空间中(其作用类似于声明静态)
- 您可以使用预处理器操作来处理此问题。这有点难看,但它很管用,而且我在野外看到了这种技术的成功应用。这是否值得努力完全是另一回事——你必须自己决定
common.h
标题:
//普通的
#共同的
#定义公共_H
#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
foo()
的实现:
foo()
如果编译为非发布:
cl /DRELEASE main.c foo.c
您有一个非内联的foo()
无论哪种情况,编译器和链接器都很满意
尽管如此,出于调试目的,我还是有点喜欢将INLINE
重新定义为static
然而,最终我不确定我是否看到了这一切真正的意义——现代调试器能够单步执行内联的函数,如果禁用优化,调试器可能不会内联函数调用。因此,您也可以在内联函数内设置断点,并使其在未优化的构建中正常工作美国
我不确定你的最终目标到底是什么。在调试/非优化构建中保留函数作为内联
有什么缺点?使用包含保护:#ifndef COMMON#define COMMON#define foo here#endifWhy Use(内联
)为什么不使用内联
(符合标准的一个)?任何一个好的编译器都有一个编译选项。不需要修改代码。禁止内联是/Ob0。@纳瓦兹:微软的编译器不支持C代码的C99,因此使用了\uu inline
扩展。除非过去几年发生了变化,否则WDK(内核模式)几乎什么也做不了使用C++来做内联代码。当人类有99%的错误时,它是浪费时间。让编译器做它知道它什么时候和为什么做内衬,它将自动地在没有你帮助的情况下自动完成。
#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
#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.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
cl test.c foo.c