关于!=与^

a^b,当且仅当a=b的时候返回值为0.因此,在很多情况下,我们可以用^来代替!=
但是,二者的效率如何呢?
为次,我做了以下测试
测试平台:window XP sp1
编译器:VC++.net 2002
程序原代码如下:

#include <iostream>

int _tmain(int argc, _TCHAR* argv[]) { 
    int a(0),b(0); 
    std::cin>>a>>b; 
    if(a != b) b=1; 
    if(a ^  b) b=2; 
    std::cout<<b<<std::endl;
    return 0; 
}

在未开启优化,项目属性使用debug时,编译后所得的机器代码为
int _tmain(int argc, _TCHAR* argv[])
{
00433350 55 push ebp
00433351 8B EC mov ebp,esp
00433353 81 EC D8 00 00 00 sub esp,0D8h
00433359 53 push ebx
0043335A 56 push esi
0043335B 57 push edi
0043335C 8D BD 28 FF FF FF lea edi,[ebp-0D8h]
00433362 B9 36 00 00 00 mov ecx,36h
00433367 B8 CC CC CC CC mov eax,0CCCCCCCCh
0043336C F3 AB rep stos dword ptr [edi]
int a(0),b(0);
0043336E C7 45 F8 00 00 00 00 mov dword ptr [a],0
00433375 C7 45 EC 00 00 00 00 mov dword ptr [b],0
std::cin>>a>>b;
0043337C 8D 45 EC lea eax,[b]
0043337F 50 push eax
00433380 8D 4D F8 lea ecx,[a]
00433383 51 push ecx
00433384 B9 BC 06 4A 00 mov ecx,offset std::cin (4A06BCh)
00433389 E8 C8 CF FF FF call std::basic_istream<:char_traits >::operator>> (430356h)
0043338E 8B C8 mov ecx,eax
00433390 E8 C1 CF FF FF call std::basic_istream<:char_traits >::operator>> (430356h)
if(a!=b) b=1;
00433395 8B 45 F8 mov eax,dword ptr [a]
00433398 3B 45 EC cmp eax,dword ptr [b]
0043339B 74 07 je main+54h (4333A4h)
0043339D C7 45 EC 01 00 00 00 mov dword ptr [b],1
if(a ^ b) b=2;
004333A4 8B 45 F8 mov eax,dword ptr [a]
004333A7 33 45 EC xor eax,dword ptr [b]
004333AA 85 C0 test eax,eax
004333AC 74 07 je main+65h (4333B5h)
004333AE C7 45 EC 02 00 00 00 mov dword ptr [b],2
std::cout<004333B5 8B 45 EC mov eax,dword ptr [b]
004333B8 50 push eax
004333B9 B9 FC 05 4A 00 mov ecx,offset std::cout (4A05FCh)
004333BE E8 3C C7 FF FF call std::basic_ostream<:char_traits >::operator<< (42FAFFh)
return 0;
004333C3 33 C0 xor eax,eax
}
004333C5 52 push edx
004333C6 8B CD mov ecx,ebp
004333C8 50 push eax
004333C9 8D 15 EA 33 43 00 lea edx,[ (4333EAh)]
004333CF E8 40 C6 FF FF call @ILT+2575(@_RTC_CheckStackVars@8) (42FA14h)
004333D4 58 pop eax
004333D5 5A pop edx
004333D6 5F pop edi
004333D7 5E pop esi
004333D8 5B pop ebx
004333D9 81 C4 D8 00 00 00 add esp,0D8h
004333DF 3B EC cmp ebp,esp
004333E1 E8 9D D4 FF FF call @ILT+6270(__RTC_CheckEsp) (430883h)
004333E6 8B E5 mov esp,ebp
004333E8 5D pop ebp
004333E9 C3 ret

明显可以看出,对于!=,只需要三句指令,mov,cmp,je就可以了
而对于^,则多了一些mov,xor,test,je
此处的cmp便相当于xor和test,但是无论是从生成的代码大小和运算速度来看,!=都优于^
但是,如果我们打开优化,使用release版的默认设置进行优化,生成的代码如下

int _tmain(int argc, _TCHAR* argv[])
{
00401D50 83 EC 08 sub esp,8
int a(0),b(0);
00401D53 33 C0 xor eax,eax
00401D55 89 44 24 00 mov dword ptr [esp],eax
00401D59 89 44 24 04 mov dword ptr [esp+4],eax
std::cin>>a>>b;
00401D5D 8D 44 24 04 lea eax,[esp+4]
00401D61 50 push eax
00401D62 8D 4C 24 04 lea ecx,[esp+4]
00401D66 51 push ecx
00401D67 B9 8C 9E 42 00 mov ecx,offset std::cin (429E8Ch)
00401D6C E8 6F FE FF FF call std::basic_istream<:char_traits >::operator>> (401BE0h)
00401D71 8B C8 mov ecx,eax
00401D73 E8 68 FE FF FF call std::basic_istream<:char_traits >::operator>> (401BE0h)
if(a!=b) b=1;
00401D78 8B 4C 24 00 mov ecx,dword ptr [esp]
00401D7C 8B 44 24 04 mov eax,dword ptr [esp+4]
00401D80 3B C8 cmp ecx,eax
00401D82 74 05 je main+39h (401D89h)
00401D84 B8 01 00 00 00 mov eax,1
if(a ^ b) b=2;
00401D89 8B D0 mov edx,eax
00401D8B 33 D1 xor edx,ecx
00401D8D 74 05 je main+44h (401D94h)
00401D8F B8 02 00 00 00 mov eax,2
std::cout<00401D94 50 push eax
00401D95 B9 EC 9D 42 00 mov ecx,offset std::cout (429DECh)
00401D9A E8 B1 FC FF FF call std::basic_ostream<:char_traits >::operator<< (401A50h)
return 0;
00401D9F 33 C0 xor eax,eax
}
00401DA1 83 C4 08 add esp,8
00401DA4 C3 ret

可以看到经过优化后,^的效率反而要高些
不过在此,编译器将原来cmp指令展开成一条mov和一条cmp
但是,相对于^而言,xor的效率相对还是要高些

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥