用汇编的眼光看C++(之判断流程)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
在我们平常的编程当中,用于判断的地方很多,但主要有下面三种方式:if-else;switch;?:。其中最后一种方式在本质上和if-else是一样的。switch和if-else其实也一样,如果我们把switch改成if(...) {} else if(...) {} else {},那么你实现的效果和switch实际差不多,熟悉的朋友都会有这样的体验。或许有的朋友还是不太相信,大家可以自己用写实例比较看一下。
(1) switch中的break重要吗?
- 21: int m = 10;
- 004017A8 mov dword ptr [ebp-4],0Ah
- 22: switch(m)
- 23: {
- 004017AF mov eax,dword ptr [ebp-4]
- 004017B2 mov dword ptr [ebp-8],eax
- 004017B5 cmp dword ptr [ebp-8],0Ah
- 004017B9 je process+33h (004017c3)
- 004017BB cmp dword ptr [ebp-8],0Bh
- 004017BF je process+42h (004017d2)
- 004017C1 jmp process+4Fh (004017df)
- 24: case 10:
- 25: printf("ten!\n");
- 004017C3 push offset string "ten!\n" (0046f028)
- 004017C8 call printf (004214d0)
- 004017CD add esp,4
- 26: break;
- 004017D0 jmp process+4Fh (004017df)
- 27:
- 28: case 11:
- 29: printf("eleven!\n");
- 004017D2 push offset string "eleven!\n" (0046f01c)
- 004017D7 call printf (004214d0)
- 004017DC add esp,4
- 30: break;
- 31:
- 32: default:
- 33: break;
- 34: }
- 35: return;
- 36: }
如果这里case10后面没有break呢?情况会不会不一样呢?
- 004017A8 mov dword ptr [ebp-4],0Ah
- 22: switch(m)
- 23: {
- 004017AF mov eax,dword ptr [ebp-4]
- 004017B2 mov dword ptr [ebp-8],eax
- 004017B5 cmp dword ptr [ebp-8],0Ah
- 004017B9 je process+33h (004017c3)
- 004017BB cmp dword ptr [ebp-8],0Bh
- 004017BF je process+40h (004017d0)
- 004017C1 jmp process+4Dh (004017dd)
- 24: case 10:
- 25: printf("ten!\n");
- 004017C3 push offset string "ten!\n" (0046f028)
- 004017C8 call printf (004214d0)
- 004017CD add esp,4
- 26:
- 27: case 11:
- 28: printf("eleven!\n");
- 004017D0 push offset string "eleven!\n" (0046f01c)
- 004017D5 call printf (004214d0)
- 004017DA add esp,4
- 29: break;
- 30:
- 31: default:
- 32: break;
- 33: }
- 34: return;
- 35: }
(2)if中的&&和||是怎么运算的?
同样,我们可以看下面一段示例。
- 21: int m = 10;
- 004017A8 mov dword ptr [ebp-4],0Ah
- 22: int n = 0;
- 004017AF mov dword ptr [ebp-8],0
- 23:
- 24: if(m == 10 && n == 0)
- 004017B6 cmp dword ptr [ebp-4],0Ah
- 004017BA jne process+3Fh (004017cf)
- 004017BC cmp dword ptr [ebp-8],0
- 004017C0 jne process+3Fh (004017cf)
- 25: {
- 26: printf("&&!\n");
- 004017C2 push offset string "&&!\n" (0046f020)
- 004017C7 call printf (004214e0)
- 004017CC add esp,4
- 27: }
- 28:
- 29: if(m == 10 || n == 0)
- 004017CF cmp dword ptr [ebp-4],0Ah
- 004017D3 je process+4Bh (004017db)
- 004017D5 cmp dword ptr [ebp-8],0
- 004017D9 jne process+58h (004017e8)
- 30: {
- 31: printf("||");
- 004017DB push offset string "||" (0046f01c)
- 004017E0 call printf (004214e0)
- 004017E5 add esp,4
- 32: }
总结:
if-else这种二分判断结构其实在现在的编程中特别重要,也特别基础。有一个关于二分法最显著的代码就是在顺序数据中进行二分查找。如果有兴趣的话,自己可以动笔试试?在这里,我有几个建议:
(1)确保函数输入的索引范围有序 (start < end)
(2)在计算中间点的时候注意不要范围溢出 (middle = start + (end - start) >> 1)
(3)考虑把你的函数修改成通用的二分法查找函数(可以考虑用const void*和函数指针)