10

我不确定 C/C++ 三元运算符的执行保证。
例如,如果给我一个地址和一个布尔值,告诉我该地址是否适合读取,我可以使用 if/else 轻松避免错误读取:

int foo(const bool addressGood, const int* ptr) {
    if (addressGood) { return ptr[0]; }
    else { return 0; }
}

但是,三元运算符 ( ?:) 能否保证除非为真,ptr否则不会被访问?或者优化编译器是否可以生成在任何情况下都可以访问的代码(可能会使程序崩溃),将值存储在中间寄存器中并使用条件赋值来实现三元运算符?addressGood
ptr

int foo(const bool addressGood, const int* ptr) {
    // Not sure about ptr access conditions here.
    return (addressGood) ? ptr[0] : 0;
}

谢谢。

4

4 回答 4

11

是的,标准保证ptr只有在addressGood为真时才能访问。请参阅有关该主题的此答案,该答案引用了标准:

条件表达式从右到左分组。第一个表达式根据上下文转换为 bool(第 4 条)。它被求值,如果为真,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值。仅计算第二个和第三个表达式之一。与第一个表达式关联的每个值计算和副作用在与第二个或第三个表达式关联的每个值计算和副作用之前排序。

(C++11 标准,第 5.16/1 段)

于 2013-07-15T23:23:49.987 回答
2

我想说,除了“是的,它由 C++ 标准保证”的答案之外:

请使用第一种形式。您要实现的目标要清楚得多。

我几乎可以保证任何理智的编译器(优化最少)无论如何都会为两个示例生成完全相同的代码。

因此,虽然知道这两种形式都实现了相同的“保护”很有用,但绝对首选使用最易读的形式。

这也意味着您不需要写注释解释它是安全的,因为 C++ 标准中的某些段落,从而使两者占用相同数量的代码空间 - 因为如果您之前不知道它,那么您可以依靠其他人也不知道这是安全的,然后花费接下来的半小时通过谷歌寻找答案,或者运行到这个线程,或者再次提出问题!

于 2013-07-15T23:37:46.697 回答
1

条件(三元)运算符保证仅在第一个操作数比较不等于 0 时评估第二个操作数,并且仅在第一个操作数比较等于 0 时评估第三个操作数。这意味着您的代码是安全的。

在对第一个操作数求值之后还有一个序列点。

顺便说一句,你不需要括号 -addressGood ? ptr[0] : 0也很好。

于 2013-07-15T23:25:50.983 回答
0

c++11/[expr.cond]/1

条件表达式从右到左分组。第一个表达式根据上下文转换为 bool(第 4 条)。它被评估,如果为真,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值。仅计算第二个和第三个表达式之一。与第一个表达式相关的每个值计算和副作用都在与第二个或第三个表达式相关的每个值计算和副作用之前排序。

于 2013-07-15T23:25:16.607 回答