17T*_*nty 15 c c++ compiler-construction boolean operator-precedence
我不假思索地编写了一些代码来检查结构的所有值是否都设置为0.为了实现这一点,我使用了:
bool IsValid() {
return !(0 == year == month == day == hour == minute == second);
}
Run Code Online (Sandbox Code Playgroud)
其中所有struct成员都是unsigned short类型.我使用代码作为更大测试的一部分,但注意到它对于不等于零的值返回false,对于全部等于零的值则返回true - 与我预期的相反.
我将代码更改为:
bool IsValid() {
return (0 != year) || (0 != month) || (0 != day) || (0 != hour) || (0 != minute) || (0 != second);
}
Run Code Online (Sandbox Code Playgroud)
但是想知道是什么导致了奇怪的行为.这是优先的结果吗?我试过谷歌这个答案,但没有发现任何东西,如果有任何术语来描述我想知道它的结果.
我使用VS9和VS8编译了代码.
Ste*_*sop 28
== 从左到右的组,所以如果所有值都为零,那么:
0 == year // true
(0 == year) == month // false, since month is 0 and (0 == year) converts to 1
((0 == year) == month) == day // true
Run Code Online (Sandbox Code Playgroud)
等等.
在一般情况下,x == y == z是不是等同于x == y && x == z你似乎期待.
CB *_*ley 15
这种行为不应该被视为奇怪的.==(以及大多数但不是所有二元运算符)的语法规则指定从左到右的分组,因此您的原始表达式等效于:
!((((((0 == year) == month) == day) == hour) == minute) == second)
Run Code Online (Sandbox Code Playgroud)
注意,当与整数类型相比时,bool具有值的表达式true将被提升为1并且具有值false将被提升为0.(在C中,等于运算符的结果int在任何情况下都是值或者是1或者0.)
这意味着,例如,((0 == year) == month)将是真实的,如果year是零,month是一个,或者year是不为零,但month是零,否则为假.
你必须考虑它的评估方式......
a == b == c
Run Code Online (Sandbox Code Playgroud)
询问他们中的两个是否相等(a和b),然后将该布尔结果与第三个值进行比较c!它不是将前两个值与第三个值进行比较.除了2个参数之外的任何东西都不会像你明显期望的那样链接.
无论它有什么价值,因为C++认为非0值在布尔上下文中是"真",你可以简单地表达你想要的东西:
return year && month && day && hour && minute && second;
Run Code Online (Sandbox Code Playgroud)
(注意:您的修改后的代码会说"月"两次并且不会测试分钟).
回到链接的==s:使用用户定义的类型和运算符重载,你可以创建一个按照你的期望进行比较的类(它甚至可以允许像0 <= x < 10数学中读取的那样"工作"),但创建一些特殊的东西只是混淆了那些已经知道(怪异的)这些东西在C++中用于内置类型的程序员.如果您热衷于深入学习C++,那么值得做一个十分钟/二十分钟的编程练习(提示:您需要比较运算符返回一个代理对象,该代理对象会记住下一个比较的左侧值是什么运营商).
最后,有时这些"奇怪的"布尔表达式很有用:例如,a == b == (c == d)可能用英语表达为"(a == b)和(c == d),OR(a!= b)和(c!= d) )",或者也许"a和b的等价与c和d的等价相同(无论真或假无关紧要)".这可能会模拟现实世界的情况,比如双重约会场景:如果喜欢/不喜欢b(他们的约会对象)喜欢/不喜欢d,那么他们要么会闲逛又玩得开心或者叫它快速退出无论如何都是无痛的...否则一对夫妇将会有一段非常繁琐的时间......因为这些事情都有意义,编译器不可能知道你不打算创建这样的表达式.
| 归档时间: |
|
| 查看次数: |
2410 次 |
| 最近记录: |