流和条件运算符的错误

时间:2018-10-17 22:14:16

标签: c++

我最近在代码中遇到了一个错误,我认为这可能是一个常见错误。我已将错误概括为一个错误,并且我想了解为什么它不生成编译器警告或错误。预先感谢。

错误是以下使用条件运算符和流运算符进行提示:

int i=0;
int array[] = {1};
std::cout << false ? array[i++] : 2;
std::cout << std::endl << "i = " << i << std::endl;

// output:
// 0
// i = 1

我假设打印的第一个数字0false的数字表示。我不确定编译器如何解释其余部分。由于array[i++]已递增,因此i得到评估。这必须是有效的语法,但是完全不需要解释。是吗?


对于那些犯了相同错误但不知道解决方法的人,更正后的代码在条件运算符的周围带有括号:

int i=0;
int array[] = {1};
std::cout << (false ? array[i++] : 2);
std::cout << std::endl << "i = " << i << std::endl;

// output:
// 2
// i = 0

此外,在条件操作之后调用流运算符会生成编译器错误:

int i=0;
int array[] = {1};
std::cout << false ? array[i++] : 2 << std::endl;
std::cout << std::endl << "i = " << i << std::endl;

// fails to compile
// error: invalid operands of types 'int' and '<unresolved overloaded function type>' to binary 'operator<<'

2 个答案:

答案 0 :(得分:2)

  

我假设打印的第一个数字0是false的数字表示。

正确。

  

我不确定编译器如何解释其余部分。

? :是三元条件运算符。第一个子表达式(std::cout << false)被评估为布尔值,如果为true,则对中间子表达式进行评估(array[i++]),否则对最后一个子表达式进行评估(2)。

std::cout的类型为std::ostream。流插入操作符返回流本身。流具有布尔值的转换运算符(自C ++ 11开始;在转换运算符之前是指向void指针的,在这种情况下,其具有相同的行为)。转换运算符的行为是:

  

如果流没有错误并且可以进行I / O操作,则返回true。

由于输出流没有错误,因此转换返回true,因此对中间子表达式(array[i++])进行了评估。

  

我想了解为什么这不会生成编译器警告或错误。

因为没有错误,而且(无可辩驳)没有任何警告。您可能打算写其他东西,但是您写的是一个有效的程序,编译器无法理解您的意图。

请注意,如果您从三元结果中删除了任何副作用:std::cout << false ? array[i] : 2;,则编译器可能会警告您,因为顶级表达式现在没有副作用了。

P.S。如果您启用了警告,则Clang会警告您的程序:

main.cpp:7:20: warning: operator '?:' has lower precedence than '<<'; '<<' will be evaluated first [-Wparentheses]
std::cout << false ? array[i++] : 2;
~~~~~~~~~~~~~~~~~~ ^
main.cpp:7:20: note: place parentheses around the '<<' expression to silence this warning
std::cout << false ? array[i++] : 2;
                   ^
main.cpp:7:20: note: place parentheses around the '?:' expression to evaluate it first
std::cout << false ? array[i++] : 2;

答案 1 :(得分:1)

int i = 0;
std::cout << false ? array[i++] : 2;

如果std::cout.operator<<(bool)没有错误,则true的结果将转换为布尔值std::cout,失败...状态。 i++得到评估,整个语句产生array[0]