简体   繁体   English

流和条件运算符的错误

[英]Mistake with streaming and conditional operators

I recently came across a bug in my code, which I think might be a common mistake. 最近,我在代码中遇到了一个错误,我认为这可能是一个常见错误。 I've generalized the mistake, and I'd like to understand why this does not generate a compiler warning or error. 我已将错误概括为一个错误,并且我想了解为什么它不生成编译器警告或错误。 Thanks in advance. 提前致谢。

The mistake is the following use of a conditional operator and streaming operator to cout: 错误是以下使用条件运算符和流运算符进行提示:

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

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

I'm assuming the first number printed 0 is the numeric representation of false . 我假设第一个打印为0的数字是false的数字表示。 I'm not sure how the compiler interprets the rest. 我不确定编译器如何解释其余部分。 The array[i++] is getting evaluated because i has been incremented. array[i++]正在评估,因为i已经增加了。 This must be valid syntax, but the interpretation is not at all expected. 这必须是有效的语法,但是完全不需要解释。 Or is it? 还是?


For those who made the same mistake but do not know the fix, the corrected code has parentheses around the conditional operator: 对于那些犯了相同错误但不知道解决方案的人,更正后的代码在条件运算符的周围带有括号:

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

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

Also, calling the streaming operator after the conditional operation would have generated a compiler error: 另外,在条件操作之后调用流运算符会生成编译器错误:

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<<'

I'm assuming the first number printed 0 is the numeric representation of false. 我假设第一个打印为0的数字是false的数字表示。

Correct. 正确。

I'm not sure how the compiler interprets the rest. 我不确定编译器如何解释其余部分。

? : ? : is the ternary conditional operator. ? :是三元条件运算符。 The first subexpression ( std::cout << false ) is evaluated as a boolean, and if it is true, then the middle subexpression is evaluated ( array[i++] ), otherwise the last subexpression is evaluated ( 2 ). 第一个子表达式( std::cout << false )被评估为布尔值,如果为true,则对中间子表达式进行评估( array[i++] ),否则对最后一个子表达式进行评估( 2 )。

std::cout is of type std::ostream . std::cout类型为std::ostream The stream insertion operator returns the stream itself. 流插入操作符返回流本身。 The stream has a conversion operator to boolean (since C++11; prior the conversion operator is to a void pointer, which has the same behaviour in this case). 流具有布尔值的转换运算符(自C ++ 11开始;在转换运算符之前是指向void指针的,在这种情况下,该指针具有相同的行为)。 The behaviour of the conversion operator is: 转换运算符的行为是:

Returns true if the stream has no errors and is ready for I/O operations. 如果流没有错误并且可以进行I / O操作,则返回true。

Since there was no errors with the output stream, the conversion returns true, and therefore the middle subexpression ( array[i++] ) is evaluated. 由于输出流没有错误,因此转换返回true,因此对中间子表达式( array[i++] )进行求值。

I'd like to understand why this does not generate a compiler warning or error. 我想了解为什么这不会生成编译器警告或错误。

Because there is no error and (arguably) nothing to warn about. 因为没有错误,并且(毫无疑问)没有警告。 You may have intended to write something else, but what you did write is a valid program and the compiler cannot read your mind to find out that this is not what you had intended. 您可能打算写其他东西,但是您写的是一个有效的程序,编译器无法理解您的意图。

Note that if you removed any side effects from the ternary results: std::cout << false ? array[i] : 2; 请注意,如果您从三元结果中删除了任何副作用: std::cout << false ? array[i] : 2; std::cout << false ? array[i] : 2; , then a compiler would likely warn you because the top level expression now has no side-effects. ,那么编译器可能会警告您,因为顶级表达式现在没有副作用了。

PS Clang does warn about your program if you've enabled warnings: 如果启用了警告,则PS 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;
 int i = 0; std::cout << false ? array[i++] : 2; 

The result of std::cout.operator<<(bool) converts to boolean true if std::cout is not in error, fail ... state. 如果std::cout没有错误,失败...状态,则std::cout.operator<<(bool)将转换为布尔值true i++ gets evaluated and the whole statement yields array[0] . i++得到评估,整个语句产生array[0]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM