C语言左移操作符(<<)和按位取反单目操作符(~)讲解
大家先判断下下面代码的运行结果
答案:
如果你做对了,那么恭喜大佬,这篇博客可能对你收益不大,全当复习好了,这是专门针对编程小白初学左移操作符(<<)和按位取反单目操作符(~)的讲解,诚挚地希望能够到xdm。接下来我将开始我的讲解,手把手带xdm拿捏这两个操作符的运算。
左移操作符(<<)
将一个数的二进制序列,去掉最左边位置的第一位(去掉高位),然后最右边位置的第一位补0(低位补0)
按位取反单目操作符(~)
将一个数的二进制序列全部按位取反
附1:
1、上述我所说的二进制序列指的都是那个数的补码,因为在计算机底层计算原理的时候,计算的不是原码,而是反码。
2、若不理解计算机底层的计算原理,大家可以看我的这篇博客,手把手带你拿捏计算机底层计算原理。
计算机底层计算原理
附2:
接下来我将用代码演示的方式来为大家解析上述题目为什么运行出来的结果是这样的
代码演示讲解:
我以brave变量左移后赋值给calorous变量为例向大家展示内存布局(内存是16进制表示)
brave、valorous变量的随机初始化
brave、valorous变量的指定初始化
brave变量左移后赋值给valorous变量
附2:
若看不懂编译器的大小端存储问题,这边推荐你看我的这篇博客,是关于编译器大小端存储的问题
编译器的大小端判断
演示代码提取:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int brave = 6, timid = -6, manful = 9;
int valorous = 0, cute = 0, courageous = 0;
valorous = brave << 1;
cute = timid << 1;
courageous = ~manful;
printf("%d\n%d\n%d\n", valorous, cute, courageous);
return 0;
}
//00000000000000000000000000000110(6的补码)
//00000000000000000000000000001100(6左移1位后的补码)
//注:正数的原码、补码、反码都是一样的,负数的原码、反码、补码是需要计算,如何计算请参考我发的博客链接,也就是计算机底层计算原理
//10000000000000000000000000000110(-6的原码)
//11111111111111111111111111111001(-6的反码)
//11111111111111111111111111111010(-6的补码)
//11111111111111111111111111110100(-6左移1位后的补码)
//11111111111111111111111111110011(-6左移1位后的反码)
//10000000000000000000000000001100(-6左移1位后的原码)
//00000000000000000000000000001001(9的补码)
//11111111111111111111111111110110(9按位取反后的补码)
//11111111111111111111111111110101(9按位取反后的反码)
//10000000000000000000000000001010(9按位取反后的原码)
右移操作符(>>)
将一个数的二进制序列,去掉最右边位置的第一位(去掉低位),然后最左边位置的第一位按原先左边第一位的数字来补,eg:是1就补1,是0就补0
代码演示讲解:
4个变量的初始状态,其中内存1代表的是变量mainstream,内存2代表的是变量 amuse,内存3代表的是变量racist,内存4代表的是变量certainty
开始进行指定初始化
进行右移后的运算结果
附3:
演示代码提取:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
//6的二进制是
//00000000 00000000 00000000 00000110
int mainstream = 6, amuse = 0;
//-6的二进制是
//10000000 00000000 00000000 00000110
int racist = -6, certainty = 0;
//6右移后的结果就是
//00000000 00000000 00000000 00000011
amuse = mainstream >> 1;
//由于-6是负数,在计算机底层计算的时候,要转换成补码才能开始计算
//10000000 00000000 00000000 00000110 (原码)
//11111111 11111111 11111111 11111001 (反码)
//11111111 11111111 11111111 11111010(补码)
//开始进行右移后的结果
//11111111 11111111 11111111 11111101(补码)
//11111111 11111111 11111111 11111100(反码)
//10000000 00000000 00000000 00000011(原码)
certainty = racist >> 1;
printf("%d\n%d\n", amuse, certainty);
return 0;
}
备注:
楼主不才,不喜勿喷,若有错误或需要改进的地方,非常感谢你的指出,我会积极学习采纳。谢谢家人们一直以来的支持和鼓励,我会继续努力再接再励创作出更多优质的文章来回报家人们的。编程爱好的xdm,若有编程学习方面的问题可以私信我一同探讨(我尽力帮),毕竟“众人拾柴火焰高”,大家一起交流学习,共同进步!