#include <stdio.h>
/*
整数在内存中存储的是补码
整数的二进制表示有3中(原反补码)
原码 反码 补码
正数的原反补码相同
负数的原反补码需要计算
7(十进制)
00000000 00000000 00000000 00000111 原码
00000000 00000000 00000000 00000111 反码
00000000 00000000 00000000 00000111 补码
-7(十进制)
10000000 00000000 00000000 00000111 原码(负数最高位为1)
11111111 11111111 11111111 11111000 反码(原码最高位1不变,其他位取反,得到反码)
11111111 11111111 11111111 11111001 补码(反码+1,得到补码)
*/
int main() {
/*
左移操作符:最左边抛弃,最右边补0
*/
/*
正整数(7)左移一位
00000000 00000000 00000000 00000111 补码(在内存中存储的二进制数,正整数的原反补码相同)
00000000 00000000 00000000 00001110 左移一位时,最左的首位丢弃,最右边补0。此时得到的是新的补码
但由于正整数原反补码相同,所以这就是原码,对应十进制数是14
*/
int a = 7;
int b = a << 1;
printf("a:%d\n", a);//a不变 7
//b在内存中是二进制的补码,而打印出来,我们所见的的是它的原码
printf("7左移一位得到:%d\n", b); //左移1位后原码 0......0000 1110 8+4+2=14
/*
负整数(-7)左移一位
11111111 11111111 11111111 11111001 补码
1111111 11111111 11111111 111110010 左移一位时,最左的首位丢弃,最右边补0,得到新的补码
1111111 11111111 11111111 111110001 反码(补码-1,得到反码)
1000000 00000000 00000000 000001110 原码(符号位不变,其他位取反,得到原码,对应十进制数是-14)
*/
int c = -7;
int d = c << 1;
printf("c:%d\n", c);//c不变 -7
//d在内存中是二进制的补码,而打印出来,我们所见的的是它的原码
printf("(-7)左移一位得到:%d\n", d); //左移1位后原码 1......0000 1110 -(8+4+2) = -14
/*
右移操作符:取决于编译器
算术移位:最右边抛弃,最左边补原符号位(正整数补0,负整数补1)
逻辑移位:最右边抛弃,最左边补0
*/
/*
正整数(7)右移一位,VS2019编译器采用的是算术移位
00000000 00000000 00000000 00000111 补码(在内存中存储的二进制数,正整数的原反补码相同)
00000000 00000000 00000000 00000011 右移一位时,最右边位丢弃,最左边补原符号位0。此时得到的是新的补码
但由于正整数原反补码相同,所以这就是原码,对应十进制数是3
*/
int m = a >> 1;
printf("a:%d\n", a);//a不变 7
printf("7右移一位得到:%d\n", m); //3
/*
负整数(-7)右移一位,VS2019编译器采用的是算术移位
11111111 11111111 11111111 11111001 补码
11111111 11111111 11111111 11111100 右移一位时,最右位丢弃,最左边位补符号位1,得到新的补码
11111111 11111111 11111111 11111011 反码(补码-1,得到反码)
10000000 00000000 00000000 00000100 原码(符号位不变,其他位取反,得到原码,对应十进制数是-4)
*/
int n = c >> 1;
printf("c:%d\n", c);//c不变 -7
printf("(-7)右移一位得到:%d\n", n); // -4
//double i = 3.14;
//double j = i << 1; //移位操作符只支持整数,不支持浮点数
//技巧:正整数和负整数左移n位,都乘以2的n次方。
// 正整数右移n位,就除以2的n次方取商。
return 0;
}
C语言-移位操作符
于 2023-05-04 11:28:35 首次发布