012 switch 语句

 

/****************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            /




 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值