如何仅为发布版本内联函数

Ben*_*min 3 c inline function c-preprocessor

// 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
Run Code Online (Sandbox Code Playgroud)

我想在我为发布版本构建时内联foo函数.我不想内联函数进行Debug构建.

我试过了,但链接器错误让我烦恼.
在这种情况下,foo函数的主体在common.h头文件中定义.
所以,如果我这样做

//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
Run Code Online (Sandbox Code Playgroud)

它将在DEBUG构建中遇到链接错误.因为两个模块试图包含common.h.
我不知道要解决它.
可能吗?

gre*_*ade 7

"简单"的解决方案是这样的:

#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
Run Code Online (Sandbox Code Playgroud)

static 有必要消除链接错误并绕过一个定义规则.

一个更好的解决办法是简单地禁用宽内联项目进行调试.GCC支持-wno-inline-functions-fno-inline-small-functions反对这些优化的选项,它也不支持内联-O1或更低(也可能-Os是).大多数编译器都有类似的选项.

我称后者为一个更好的解决方案,因为它应该指示编译器忽略inline提示,省去了麻烦的预处理指令的需要.

  • +1用于编译器标志.这样做更好,因为编译器可能会选择忽略内联语句或未声明的内联函数. (2认同)

Mic*_*urr 5

要实现的基本要点是inline关键字(或Microsoft的__inlineC扩展 - 因为MSVC不支持C99)本质上是违反一个定义规则的过程.如果你考虑一下 - 这就是它的真实情况,因为编译器没有义务实际执行任何内联.

因此,当您拥有一个inline函数时,您可以在多个模块中定义函数.实际上,您有义务在任何实际使用该功能的模块中定义它.

但是,如果您不将该函数声明为inline,则必须确保您只有一个定义(如果实际使用它,则只有一个定义).对于非成员函数(C中的所有函数),有几种方法可以解决这个问题:

  • 声明函数static以更改它与内部的链接(请注意,您可以使用static inline函数开始).
  • 在C++中,您可以将它们放在匿名命名空间中(其效果类似于声明静态)
  • 您可以使用预处理器操作来处理此问题.它有点难看,但它有效,而且我已经看到了在野外成功使用的技术.是否值得努力是另一回事 - 你必须自己决定.

基本上,您需要做的是在单独的.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 */
Run Code Online (Sandbox Code Playgroud)

执行foo():

// foo.c
#ifndef FOO_C
#define FOO_C

#include <stdio.h>
#include "common.h"


INLINE void foo()
{
    printf("foo\n");
}

#endif /* FOO_C */
Run Code Online (Sandbox Code Playgroud)

一个示例程序:

// main.c
#include<stdio.h>
#include "common.h"

int main()
{
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在如果你编译发布:

cl /DRELEASE main.c foo.c
Run Code Online (Sandbox Code Playgroud)

foo()inline(或__inline视情况而定).

如果您为非发布编译:

cl  test.c foo.c
Run Code Online (Sandbox Code Playgroud)

你有一个非内联foo().

在任何一种情况下,编译器和链接器都很满意.

说了这么多,我挺喜欢的建议,也许重新定义INLINEstatic用于调试目的.

但是,最终我不确定我是否真正看到了这一点 - 现代调试器能够逐步执行函数,inline如果禁用优化,调试器可能不会内联函数调用.因此,您也可以在内联函数中设置断点,并使其在非优化构建中正常工作.

我不确定你究竟是什么样的最终目标.inline在调试/非优化版本中保留函数有什么缺点?