关于运算符优先级/评估的C / C ++编译器有多严格?

时间:2013-10-14 20:16:27

标签: c++ c operators logical-operators

这个问题一直存在我的脑海中,所以有时间让它出来,看看你们有什么话要说。

在C / C ++中,运算符优先级由C规范定义,但与所有内容一样,可能存在后门或未知/未知的事情,编译器可能会以“优化”的名义使用这些内容,这会使您的应用程序陷入困境结束。

举个简单的例子:

bool CheckStringPtr(const char* textData)
{
    return (!textData || textData[0]==(char)0);
}

在这种情况下,我测试指针是否为空然后我检查第一个char是零,本质上这是一个零长度字符串的测试。从逻辑上讲,这两个操作是可以交换的,但如果在某些情况下会发生这种情况,那么它会崩溃,因为它试图读取一个不存在的内存地址。

所以问题是:是否有任何强制执行操作符/函数的顺序,我知道最安全的方法是使用彼此之下的2个IF,但这种方式应该是相同的假设运营商的评估顺序永远不会改变。 因此,C / C ++规范强制要求的编译器不会改变评估顺序,或者有时它们是否允许更改顺序,例如它取决于编译器参数,尤其是优化?

2 个答案:

答案 0 :(得分:11)

首先请注意,优先级评估顺序是两个不同的(很大程度上不相关的)概念。

  

C / C ++规范强制要求编译器不改变评估顺序吗?

编译器必须生成与C语言标准保证的行为一致的行为。它可以自由改变,例如评估的顺序,只要整体观察到的行为不变。

  

逻辑上,这2个操作是可交换的,但如果在某些情况下会发生这种情况,那么它就会崩溃

||&&被定义为具有short-circuit语义;他们可能不会互换。

答案 1 :(得分:3)

C和C ++标准明确支持短路评估,因此需要在右侧之前评估&&||?运算符的左侧操作数 - 手边。

其他“序列点”包括逗号运算符(不要与在f(a, b)中分隔函数参数的逗号混淆),语句结束(;),以及在函数的参数和对函数的调用。

但是在大​​多数情况下,评估顺序(不要与优先级混淆)是实现定义的。因此,例如,不要依赖ff(x) + g(y)等表达式中首先调用。