我最近在代码中遇到了一个错误,我认为这可能是一个常见错误。我已将错误概括为一个错误,并且我想了解为什么它不生成编译器警告或错误。预先感谢。
错误是以下使用条件运算符和流运算符进行提示:
int i=0;
int array[] = {1};
std::cout << false ? array[i++] : 2;
std::cout << std::endl << "i = " << i << std::endl;
// output:
// 0
// i = 1
我假设打印的第一个数字0
是false
的数字表示。我不确定编译器如何解释其余部分。由于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<<'
答案 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]
。