为什么要使用“函数地址==NULL”而不是“false”?

22

在浏览一些旧代码时,我发现了这样的函数:

static inline bool EmptyFunc()
{
    return (void*) EmptyFunc == NULL;
}

这个跟那个有什么不同:

static inline bool EmptyFunc()
{
    return false;
}

这段代码被创建用于在多种平台上编译,如PS2、Wii和PC等... 是否有使用第一个函数的理由?例如更好的优化或避免一些奇怪的编译器错误?


4
我想,这是因为如果你只返回 false,编译器可以自由地优化掉那个函数...但是任何实际使用它的地方都应该防止同样的优化。嗯,EmptyFunc 在哪里被使用?另外,为什么要将函数指针强制转换成 void*?这对函数指针来说没有意义... - Cameron
6
只是猜测,但看起来他们试图强制编译器生成一个非内联版本的函数。当您获取函数的指针时,这种情况可能会发生。 - Captain Obvlious
2
“EmptyFunc” 被用作用户输入注册过程中的回调函数,当给定的回调函数返回 true 时,该程序将遍历每个已注册的回调函数并标记相应事件已触发。 - Vytis Valentinavičius
3
@CaptainObvlious,在第一个问题中,没有任何内容会阻止编译器在调用函数时对其进行优化。也许有一些编译器不会这样做,但没有任何基本的障碍。 - edA-qa mort-ora-y
5
另一个选择可能是糟糕的编码。 - BЈовић
显示剩余7条评论
2个回答

10

从语义上来说,这两个函数是相同的:它们总是返回false*。将第一个表达式折叠为常量值"false"完全符合标准,因为这不会改变任何可观察的副作用(其中没有任何副作用)。由于编译器看到整个函数,它也可以自由地优化掉对它的任何调用,并将其替换为常量"false"值。

也就是说,第一种形式没有“通用”值,很可能是程序员犯的错误。唯一的可能性是它利用了特定编译器/版本中的某些特殊行为(或缺陷)。然而,我不知道它的目的是什么。如果您希望防止内联使用特定于编译器的属性将是正确的方法-其他任何方法都容易在编译器更改时出现问题。

(*这假设 NULL 从未定义为 EmptyFunc ,否则将返回 true )。


1
+1 这也是我的感觉,它是为了解决编译器问题而进行的工作(我见过更糟糕的编译器补丁,但至少代码有文档记录,不像这里!)。 - syam

3
严格来说,函数指针可能不能转换为void指针,这时发生的情况超出了标准范围。C11标准在J.5.7中将其列为“常见扩展”(我怀疑C++也适用此规则)。因此,两种情况之间唯一的区别在于前者是不可移植的。
看起来,前一版本最有可能的原因是混淆的程序员或混淆的编译器。缺少解释性注释可以确定程序员混淆/粗心。
声明函数为inline,然后试图通过在代码中包含函数地址来欺骗编译器不进行内联代码并没有什么意义。因此,我认为我们可以排除这个理论,除非当然程序员混淆并认为这是有意义的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接