左移32位的结果为啥是0呢?
#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
一般编译器和系统,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 了 从结果上看,
直接写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
页:
[1]