在一些遗留代码中浏览我发现了这样的功能:
static inline bool EmptyFunc()
{
return (void*) EmptyFunc == NULL;
}
和这个有什么区别:
static inline bool EmptyFunc()
{
return false;
}
这段代码是为了在几个不同的平台下编译而创建的,比如 PS2、Wii、PC……有什么理由使用第一个函数吗?喜欢更好的优化或避免一些奇怪的编译器错误行为?
在一些遗留代码中浏览我发现了这样的功能:
static inline bool EmptyFunc()
{
return (void*) EmptyFunc == NULL;
}
和这个有什么区别:
static inline bool EmptyFunc()
{
return false;
}
这段代码是为了在几个不同的平台下编译而创建的,比如 PS2、Wii、PC……有什么理由使用第一个函数吗?喜欢更好的优化或避免一些奇怪的编译器错误行为?
从语义上讲,这两个函数是相同的:它们总是返回 false*。标准完全允许将第一个表达式折叠为常数值“false”,因为它不会改变任何可观察到的副作用(其中没有)。由于编译器看到了整个函数,它还可以自由地优化对它的任何调用并将其替换为常量“false”值。
也就是说,第一种形式没有“通用”值,很可能是程序员的错误。唯一的可能性是它利用了特定编译器/版本中的一些特殊行为(或缺陷)。然而我不知道结果是什么。如果您希望使用特定于编译器的属性来防止内联,那将是正确的方法——如果编译器发生变化,其他任何事情都容易破坏。
(*这假设NULL
从未定义为 is EmptyFunc
,这将导致true
被返回。)。
严格来说,函数指针不能转换为 void 指针,然后发生的事情超出了标准的范围。C11 标准将其列为 J.5.7 中的“通用扩展”(我怀疑这同样适用于 C++)。因此,这两种情况的唯一区别在于前者是不可移植的。
看起来前一个版本最可能的原因是程序员困惑或编译器困惑。我们可以肯定地说,由于缺少解释性注释,程序员感到困惑/草率。
inline
将函数声明为然后尝试通过在代码中包含函数地址来欺骗编译器不内联代码并没有多大意义。所以我认为我们可以排除这种理论,除非程序员当然感到困惑并认为这是有道理的。