鱼C论坛

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

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

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

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

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

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

int main()
{
    int i = 32;
    printf("左移32:%x\n", 0xFEDCBA98 << i);
    printf("直接左移32:%x\n", 0xFEDCBA98 << 32);
    return 0;
}
左移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 是进行了循环左移,变成了原数

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

int main (){
        int i = 32;
        int j;
        int k;

        j = 1 << i;
        printf("%x", j);
        
        k = 1 << 32;
        
        printf("\n%x",k);
        
        return 0;
}

汇编代码
        .file        "main.c"
        .def        ___main;        .scl        2;        .type        32;        .endef
        .section .rdata,"dr"
LC0:
        .ascii "%x\0"
LC1:
        .ascii "\12%x\0"
        .text
.globl _main
        .def        _main;        .scl        2;        .type        32;        .endef
_main:
        pushl        %ebp
        movl        %esp, %ebp
        andl        $-16, %esp
        pushl        %ebx
        subl        $44, %esp
        call        ___main
        movl        $32, 20(%esp)
        movl        20(%esp), %eax
        movl        $1, %edx
        movl        %edx, %ebx
        movb        %al, %cl
        sall        %cl, %ebx
        movl        %ebx, %eax
        movl        %eax, 24(%esp)
        movl        24(%esp), %eax
        movl        %eax, 4(%esp)
        movl        $LC0, (%esp)
        call        _printf
        movl        $0, 28(%esp)
        movl        28(%esp), %eax
        movl        %eax, 4(%esp)
        movl        $LC1, (%esp)
        call        _printf
        movl        $0, %eax
        addl        $44, %esp
        popl        %ebx
        leave
        ret
        .def        _printf;        .scl        2;        .type        32;        .endef

去掉没用的
        call        ___main
    
        movl        $32, 20(%esp)       这句是把32 赋值给i
    
        movl        20(%esp), %eax      这块是循环左移的
        movl        $1, %edx
        movl        %edx, %ebx
        movb        %al, %cl
        sall        %cl, %ebx
        movl        %ebx, %eax          求出的值放到寄存器eax中
        movl        %eax, 24(%esp)      这里把eax的值给j,然后打印
        movl        24(%esp), %eax
        movl        %eax, 4(%esp)
        movl        $LC0, (%esp)
        call        _printf
    
        movl        $0, 28(%esp)        这里直接把0给k,没有运算过程
    
        movl        28(%esp), %eax
        movl        %eax, 4(%esp)
        movl        $LC1, (%esp)
        call        _printf

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

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

int main (){

        int k;
        k = 1 << 31;
        return 0;
}
汇编:
        .file        "main.c"
        .def        ___main;        .scl        2;        .type        32;        .endef
        .text
.globl _main
        .def        _main;        .scl        2;        .type        32;        .endef
_main:
        pushl        %ebp
        movl        %esp, %ebp
        andl        $-16, %esp
        subl        $16, %esp
        call        ___main 
        movl        $-2147483648, 12(%esp)        直接有结果,没运算
        movl        $0, %eax
        leave
        ret
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-18 16:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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