【问题标题】:C static inline function redefinition rulesC静态内联函数重定义规则
【发布时间】:2011-06-23 01:04:53
【问题描述】:

假设在bar.h可能存在:

static inline int fun () { return 2; }

并确保fun 始终被定义foo.h 包含以下内容:

static inline int fun () { return 3; }

bar.h 包含定义时,以下是否会引发未定义的行为?

#include "foo.h" /* ensure there is always a definition */
#include "bar.h" /* use the bar definition if it exists */

int main () {
   /* ... */
   int x = fun ();
   /* ... */

使用 gcc (4.0.1)(旧的,但这是我目前所拥有的)行为符合预期 - 当 bar 版本丢失时使用 foo 版本,而 bar 版本在存在时使用。

【问题讨论】:

  • 我应该指出 void func()void func(void) 在 C 语言中的细微差别。
  • @Chris 您是否建议我可以通过将显式 void 添加到签名中的两个定义之一来避免未定义的行为?
  • 不,C 不允许重载。看起来你打算int fun(void)int fun() 更准确。

标签: c function static shadow undefined-behavior


【解决方案1】:

不,这是不允许的。 fun() 的那些定义声明 fun() 具有内部链接(由于 static),并且 C 标准中的 §6.9 说:

不超过一个 每个的外部定义 用内部声明的标识符 翻译单元中的链接。

违反“shall”子句是未定义的行为,这意味着您的程序的语义完全未定义,编译器不必发出错误消息。

【讨论】:

  • 那个参考正是我想要的。谢谢。
【解决方案2】:

你不能这样做,你的编译器也不应该让你这样做。

只有当所有定义都相同时,您才能对非静态内联函数有多个定义(但每个 TU 不能超过一个定义)。头文件中定义的内联函数必然会发生这种情况。

对于静态链接,每个 TU 可以有不同的定义,但每个 TU 仍然只能有一个定义。

(抱歉多次修改。)

【讨论】:

  • 我试过gcc -W -Wall -Wextra -pedantic 没有抱怨。只有-ansi 才有问题。但是,到那时,inline 也有问题。
  • @ezpz:你到底在编译什么?我用你的例子得到“错误:重新定义”。你在头文件中包含守卫吗?
  • 不包括警卫。每个标头中只有一个定义,并且来源主要在我的问题中列出。我想当我得到一个时,我将不得不尝试一个更新的编译器版本。
  • @ezpz - 仅供参考,ansi 的问题是因为 inline 是 C99 的补充,而 ansi 标志强制 C89 标准。
【解决方案3】:

如果你想达到同样的效果,你可以使用一个无害的宏:

// foo.h - include guards omitted because of iPhone
#ifndef VALUE
# define VALUE 2
#endif

static inline int fun() { return VALUE; }

// bar.h
#define VALUE 3
#include "foo.h"

包括订单翻转,但它没有完整的宏版本那么可怕(恕我直言,这根本不可怕,但我不知道你/你的工作场所与宏的关系。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 2011-01-14
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多