前段时间代码出了个和题目有关的Bug,一直奇怪为何出问题。无奈反了一下,突然就明白了,原来&&、&、||和|的用法,书本上并没有讲全。
&&和&的差别,或许不只是我们从书本表面理解的那样。看两段例子:
1 //一A
2 #include <iostream>
3 using namespace std;
4
5 int main()
6 {
7 int a = 2,b = 3;
8 if((a < 2) && (++b < 3))
9 {
10 cout<<"Not skip"<<endl;
11 }
12
13 cout<<a<<","<<b<<endl;
14
15 return 0;
16 }
输出结果:2,3
1 一B
2 #include <iostream>
3 using namespace std;
4
5 int main()
6 {
7 int a = 2,b = 3;
8 if((a < 2) && (++b < 3))
9 {
10 cout<<"Not skip"<<endl;
11 }
12
13 cout<<a<<","<<b<<endl;
14
15 return 0;
16 }
输出结果:2,4
&&:(Ea && Eb)时,如果Ea==false,则不再去计算Eb。
&:(Ea & Eb)时,无论Ea为何值,都要计算Eb。
————————————————————————————————————————————————
||和|与&&和&类似。
1 二A
2 #include <iostream>
3 using namespace std;
4
5 int main()
6 {
7 int a = 2,b = 3;
8 if((a == 2) || (++b < 3))
9 {
10 cout<<"Not skip"<<endl;
11 }
12
13 cout<<a<<","<<b<<endl;
14
15 return 0;
16 }
输出结果:2,3
//二B(--!不好意思,没考虑到会这样)
#include <iostream>
using namespace std;
int main()
{
int a = 2,b = 3;
if((a == 2) | (++b < 3))
{
cout<<"Not skip"<<endl;
}
cout<<a<<","<<b<<endl;
return 0;
}
输出结果:2,4
||:(Ea || Eb)时,若Ea==true,不再计算Eb。
|:(Ea || Eb)时,先计算Ea与Eb的结果,再执行|。
从可执行文件的反汇编中也能看出端倪。
;二A-DEBUG
int a = 2,b = 3;
001C14DE mov dword ptr [a],2
001C14E5 mov dword ptr [b],3
if((2 == a) || (b++))
001C14EC cmp dword ptr [a],2 ;比较a和2
001C14F0 je main+4Dh (1C150Dh) jump equal,跳转到1C150Dh,即if程序块内
001C14F2 mov eax,dword ptr [b]
001C14F5 mov dword ptr [ebp-0DCh],eax
001C14FB mov ecx,dword ptr [b]
001C14FE add ecx,1
001C1501 mov dword ptr [b],ecx
001C1504 cmp dword ptr [ebp-0DCh],0
001C150B je main+78h (1C1538h)
{
cout<<"Not skip"<<endl;
001C150D mov esi,esp
001C150F mov eax,dword ptr [__imp_std::endl (1CA340h)]
001C1514 push eax
001C1515 push offset string "Not skip" (1C7870h)
001C151A mov ecx,dword ptr [__imp_std::cout (1CA344h)]
001C1520 push ecx
001C1521 call std::operator<<<std::char_traits<char> > (1C1159h)
001C1526 add esp,8
001C1529 mov ecx,eax
001C152B call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (1CA32Ch)]
001C1531 cmp esi,esp
001C1533 call @ILT+420(__RTC_CheckEsp) (1C11A9h)
}
cout<<a<<","<<b<<endl;
;二B-DEBUG
int a = 2,b = 3;
008C14DE mov dword ptr [a],2
008C14E5 mov dword ptr [b],3
if((2 == a) | (b++))
008C14EC xor eax,eax
008C14EE cmp dword ptr [a],2
008C14F2 sete al ;如果相等,ZF=1。不明白,哪位大牛知道什么意思麻烦留言给我解释一下
008C14F5 or eax,dword ptr [b]
008C14F8 mov dword ptr [ebp-0DCh],eax
008C14FE mov ecx,dword ptr [b]
008C1501 add ecx,1
008C1504 mov dword ptr [b],ecx
008C1507 cmp dword ptr [ebp-0DCh],0
008C150E je main+7Bh (8C153Bh) ;这里直接跳到if块外面。
{
cout<<"Not skip"<<endl;
008C1510 mov esi,esp
008C1512 mov eax,dword ptr [__imp_std::endl (8CA340h)]
008C1517 push eax
008C1518 push offset string "Not skip" (8C7870h)
008C151D mov ecx,dword ptr [__imp_std::cout (8CA344h)]
008C1523 push ecx
008C1524 call std::operator<<<std::char_traits<char> > (8C1159h)
008C1529 add esp,8
008C152C mov ecx,eax
008C152E call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (8CA32Ch)]
008C1534 cmp esi,esp
008C1536 call @ILT+420(__RTC_CheckEsp) (8C11A9h)
}
cout<<a<<","<<b<<endl;
008C153B mov esi,esp
定是编译器做了优化。
测试了一下GCC、VC都会有这样的优化,Java不会反,但是编了段代码试了一下,也是一样的。
原来编译器们都知道,就我不知道.......