【问题标题】:Declare function as non-static and implement as static inline将函数声明为非静态并实现为静态内联
【发布时间】:2015-02-09 16:29:35
【问题描述】:

我想为我的函数编写不同的实现,有些是inline,有些不是。因此,我想将函数声明为:

// MyHeader.h
int myFunc(void);

#if DO_INLINE
static inline int myFunc(void) { return 42; }
#endif

然后还有:

// MySource.c
#if !DO_INLINE
#include "myHeader.h"
int myFunc(void) { return 42; }
#endif

我会在编译时指定DO_INLINE

MSVC 对此没有任何问题,但 GCC (4.1.1) 抱怨说我在声明一个静态函数后声明它是非静态的。如果我从多个编译单元中删除static 限定符和#include "MyHeader.h",它将抱怨多个定义。 (好像inline 函数是extern。)我不太明白为什么编译器会出现这个问题。

我认为这应该是非常明显和明确的:

int myFunc(void);
static inline int myFunc(void) { return 42; }

它不应该要求声明是static

也就是说,我正在努力避免解决我的问题:

#if DO_INLINE
#define MAYBE_STATIC static
#else
#define MAYBE_STATIC 
#endif

MAYBE_STATIC int myFunc(void);

编辑:这是一个更现实的用例:http://codepad.org/OkC0Su3v

【问题讨论】:

  • 你能给出一个完整的头文件示例,它是如何与 MSVC 一起使用的吗?无论如何都会有一些预处理器的东西(提供或不提供函数定义)。 MAYBE_STATIC 方法并不难阅读,至少它很常见,很容易识别。通过比较来自不同文件的地址,可以观察到函数是否是静态的(因此可以认为是接口的一部分)。
  • 对于 C 标准:如果标识符在链接上存在分歧,则行为未定义。该标准的基本原理提到了两件事:C89 之前的编译器和链接器变化很大。不需要实现来捕获void foo(void) { void bar(void); bar(); } static void bar(void);。 Wrt 允许在以后的声明中“覆盖”链接:通常,声明以后不能更改,链接规则与类型的规则有些一致:float n; int n; 无效,类型不能被覆盖。
  • 最后,我可以想象静态和外部函数必须以不同方式调用的平台,因此编译器可能需要在调用时知道。
  • 我明白了,谢谢。我会尝试一下,也许我有一个想法。关于我的最后一条评论:静态和外部函数的不同 ABI 至少很难使用函数指针,仔细想想,这听起来不像是标准的意图。
  • 这个例子看起来你总是提供一个外部定义。内联(在某种程度上)独立于链接,提供外部函数并可选地在标题中提供内联定义有什么问题吗? Gcc 似乎期望inline 的外部定义(没有extern),但不是extern inline;不过,我找不到标准规定的地方。

标签: c gcc static inline-functions


【解决方案1】:

这个 header.h 应该可以工作:

// MyHeader.h
#if DO_INLINE
static inline int myFunc(void) { return 42; }
#else
int myFunc(void);
#endif

【讨论】:

  • 这与我在底部用 MAYBE_STATIC 写的类似,只是有重复的代码。我实际上有很多(几十个)类似 myFunc 的函数,真的不想重复它们。
【解决方案2】:

足够仔细地想通了。应将实现定义为“extern inline”:

// MyHeader.h
int myFunc(void);

#if DO_INLINE
extern inline int myFunc(void) { return 42; }
#endif

编译器将在它认为合适的地方内联这个函数,但仍然将它作为一个函数编译一次,以使其可用于链接。那部分我不需要,但它并没有真正伤害。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2011-06-04
    • 1970-01-01
    相关资源
    最近更新 更多