鱼C论坛

 找回密码
 立即注册
查看: 644|回复: 2

左移32位的结果为啥是0呢?

[复制链接]
发表于 2022-1-24 16:21:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main()
  4. {
  5.     int i = 32;
  6.     printf("左移32:%x\n", 0xFEDCBA98 << i);
  7.     printf("直接左移32:%x\n", 0xFEDCBA98 << 32);
  8.     return 0;
  9. }
复制代码

左移32:fedcba98
直接左移32:0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-1-24 17:09:12 | 显示全部楼层
一般编译器和系统,C中整型都是4个字节,一个字节二进制位是8位,四个字节也就是32位
也就是说,C中一个整数,在底层存储中,占了  32个 二进制位

左移就是针对二进制 形式进行操作的
比如一个十进制数是1 ,在内存中存储的为  
                     0000 0000 0000 0000 0000 0000 0000 0001
左移一位        0000 0000 0000 0000 0000 0000 0000 0010
左移两位        0000 0000 0000 0000 0000 0000 0000 0100

一个32位的数,左移32位,那么它的有效位全没了,就变成0 了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-24 22:24:29 | 显示全部楼层
从结果上看,

直接写32 是进行了左移,变成了0
变量赋值32 是进行了循环左移,变成了原数

反汇编看一下就知道了
方便查看汇编,代码先写成这样
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main (){
  4.         int i = 32;
  5.         int j;
  6.         int k;

  7.         j = 1 << i;
  8.         printf("%x", j);
  9.         
  10.         k = 1 << 32;
  11.         
  12.         printf("\n%x",k);
  13.         
  14.         return 0;
  15. }
复制代码


汇编代码
  1.         .file        "main.c"
  2.         .def        ___main;        .scl        2;        .type        32;        .endef
  3.         .section .rdata,"dr"
  4. LC0:
  5.         .ascii "%x\0"
  6. LC1:
  7.         .ascii "\12%x\0"
  8.         .text
  9. .globl _main
  10.         .def        _main;        .scl        2;        .type        32;        .endef
  11. _main:
  12.         pushl        %ebp
  13.         movl        %esp, %ebp
  14.         andl        $-16, %esp
  15.         pushl        %ebx
  16.         subl        $44, %esp
  17.         call        ___main
  18.         movl        $32, 20(%esp)
  19.         movl        20(%esp), %eax
  20.         movl        $1, %edx
  21.         movl        %edx, %ebx
  22.         movb        %al, %cl
  23.         sall        %cl, %ebx
  24.         movl        %ebx, %eax
  25.         movl        %eax, 24(%esp)
  26.         movl        24(%esp), %eax
  27.         movl        %eax, 4(%esp)
  28.         movl        $LC0, (%esp)
  29.         call        _printf
  30.         movl        $0, 28(%esp)
  31.         movl        28(%esp), %eax
  32.         movl        %eax, 4(%esp)
  33.         movl        $LC1, (%esp)
  34.         call        _printf
  35.         movl        $0, %eax
  36.         addl        $44, %esp
  37.         popl        %ebx
  38.         leave
  39.         ret
  40.         .def        _printf;        .scl        2;        .type        32;        .endef
复制代码


去掉没用的

  1.         call        ___main
  2.    
  3.         movl        $32, 20(%esp)       这句是把32 赋值给i
  4.    
  5.         movl        20(%esp), %eax      这块是循环左移的
  6.         movl        $1, %edx
  7.         movl        %edx, %ebx
  8.         movb        %al, %cl
  9.         sall        %cl, %ebx
  10.         movl        %ebx, %eax          求出的值放到寄存器eax中
  11.         movl        %eax, 24(%esp)      这里把eax的值给j,然后打印
  12.         movl        24(%esp), %eax
  13.         movl        %eax, 4(%esp)
  14.         movl        $LC0, (%esp)
  15.         call        _printf
  16.    
  17.         movl        $0, 28(%esp)        这里直接把0给k,没有运算过程
  18.    
  19.         movl        28(%esp), %eax
  20.         movl        %eax, 4(%esp)
  21.         movl        $LC1, (%esp)
  22.         call        _printf
复制代码


结论:"<< 32" 在编译的时候就已经计算得到结果了
应该是 "<< i"因为是变量,编译的时候还没有计算,运行的时候才会执行

验证一下 <<31 汇编是不是也是直接有结果
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main (){

  4.         int k;
  5.         k = 1 << 31;
  6.         return 0;
  7. }
复制代码

汇编:
  1.         .file        "main.c"
  2.         .def        ___main;        .scl        2;        .type        32;        .endef
  3.         .text
  4. .globl _main
  5.         .def        _main;        .scl        2;        .type        32;        .endef
  6. _main:
  7.         pushl        %ebp
  8.         movl        %esp, %ebp
  9.         andl        $-16, %esp
  10.         subl        $16, %esp
  11.         call        ___main
  12.         movl        $-2147483648, 12(%esp)        直接有结果,没运算
  13.         movl        $0, %eax
  14.         leave
  15.         ret
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 17:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表