/****************012 switch 语句*********************************
* C 语言精彩编程的第12个例子:给出一个不多于5位的正整数,要求:1、求
* 他是几位数;2、分别打印出每一位数字;3、按逆序打印出各位数字。
****************************************************************/
#include<stdio.h>
void main()
{
int num;
//下面定义的各变量,分别代表个位、十位、百位..
int indev, ten,hundred, thousand,ten_thousand,hundred_thousand,place;
printf("请输入一个整数(0~99999):");
scanf("%d",&num);
if(num>99999)
place=6;
else if(num>9999)
place=5;
else if(num>999)
place=4;
else if(num>99)
place=3;
else if(num>9)
place=2;
else
place=1;
printf("place = %d\n",place);
printf("每位数字为:");
hundred_thousand=num/10000;
ten_thousand=(num-hundred_thousand*100000)/10000;
thousand =(num-hundred_thousand*100000-ten_thousand*10000)/1000;
hundred =(num-hundred_thousand*100000-ten_thousand*10000-thousand*1000)/100;
ten=(num-hundred_thousand*100000-ten_thousand*10000-thousand*1000-hundred*100)/10;
indev=(num-hundred_thousand*100000-ten_thousand*10000-thousand*1000-hundred*100-ten*10);
//判断num的位数,并根据位数做出相应的输出
switch(place)
{
case 1: printf("%d",indev);
printf("\n反序数字为:");
printf("%d\n",indev);
break;
case 2: printf("%d,%d",ten,indev);
printf("\n反序数字为:");
printf("%d%d\n",indev,ten);
break;
case 3: printf("%d,%d,%d",hundred,ten,indev);
printf("\n反序数字为:");
printf("%d%d%d\n",indev,ten,hundred);
break;
case 4: printf("%d,%d,%d,%d",thousand,hundred,ten,indev);
printf("\n反序数字为:");
printf("%d%d%d%d\n",ten,indev,hundred,thousand);
break;
case 5: printf("%d,%d,%d,%d,%d",ten_thousand,thousand,hundred,ten,indev);
printf("\n反序数字为:");
printf("%d%d%d%d%d\n",indev,ten,hundred,thousand,ten_thousand);
break;
case 6: printf("%d,%d,%d,%d,%d,%d",hundred_thousand,ten_thousand,thousand,hundred,ten,indev);
printf("\n反序数字为:");
printf("%d%d%d%d%d%d\n",indev,ten,hundred,thousand,ten_thousand,hundred_thousand);
break;
default: printf("Not find.\n");
}
}
编译器处理的结果中要关注的部分:
这个例子的关键部分 switch语句的处理部分 :
movl %eax, -8(%ebp)
cmpl $6, -32(%ebp) # place 和 6 比较
ja L21 # 大于则转到 default
movl -32(%ebp), %eax # %eax = place
sall $2, %eax # eax =eax*4
movl L22(%eax), %eax # eax = L22:eax
jmp *%eax
.p2align 2
.align 4
L22:
.long L21
.long L15
.long L16
.long L17
.long L18
.long L19
.long L20
关于比较运算,不明白的情况
cmpl $99999, -4(%ebp) # 比较99999和num ; 前面见到的比较是否小于的时候编译器吧数字减一,这里没有。 原因还不清楚
jle L4 # 不大于跳
movl $6, -32(%ebp) # place =6
jmp L5 # 退出循环
前面的几个例子中, 编译器前面见到的比较是否小于的时候编译器吧数字减一,这里没有,目前看不明白差别,需要在进一步了解编译器工作原理后才能明白。
关于算数运算的:
hundred_thousand=num/100000;
movl -4(%ebp), %ecx # %ecx = num
movl $351843721, %eax # num/100000:编译器优化计算 num/100000自动取的幻数
imull %ecx # edx:eax = %eax*%ecx (运算结果由32位扩展到64位,使用2个32位寄存器)
sarl $13, %edx # 对运算结果的高32位右移13位,就是对运算结果右移32+13=45位,2^45=35184372088832 ,edx = num*351843721/35184372088832
movl %ecx, %eax # %eax = num
sarl $31, %eax # 右移31位, 取原数字的符号位
subl %eax, %edx # %edx=%edx-%eax 趋零取整调整
movl %edx, %eax # num/100000 的计算结果
这个运算也被搞的过程复杂
movl -28(%ebp), %edx # edx = hundred_thousand \ 用这样的办法计算
movl %edx, %eax # eax = hundred_thousand | hundred_thousand*100000
sall $2, %eax # eax = hundred_thousand*4 | 编译器优化好神奇啊
addl %edx, %eax # eax = hundred_thousand*5 |
leal 0(,%eax,4), %edx # edx = eax%4 = hundred_thousand*20 |
addl %edx, %eax # eax = hundred_thousand*25 |
leal 0(,%eax,4), %edx # edx = eax*4 = hundred_thousand*100 |
addl %edx, %eax # eax =edx+eax = hundred_thousand*125 |
leal 0(,%eax,4), %edx # edx = eax *4 =hundred_thousand*500 |
addl %edx, %eax # eax = hundred_thousand* 625 |
leal 0(,%eax,4), %edx # edx = eax *4 = hundred_thousand* 2500 |
addl %edx, %eax # eax = hundred_thousand*3125 |
movl %eax, %edx # |
sall $5, %edx # edx = hundred_thousand* 100000 /