本期介绍
主要介绍:位操作符有哪些,位操作符操作的对象,整数在内存中是如何存放的,有哪些位操作符,各自又都具备何种功能。
在C语言中除了算数操作符、关系操作符、逻辑操作符外还有一类操作符 “ 位操作符 ”。这类操作符可以直接对内存中存储的二进制位进行操作,但有个前提条件:其所操作的对象只能是整形家族的成员(char、short、int、long、longlong)。为什么呢?拿浮点型举个例子吧。你看啊,我们都知道整形与浮点型在内存中的存储方式是完全不同的,如果胡乱的按照处理整形数据时的观念操作浮点数,那必然乱套啊。所以说到底位操作符就是专门为操作整数而存在的,下面就来介绍一下吧。
在讲位操作符之前我们先需要了解一下整数在内存中的存储形式才行。我们都知道一个整数在内存中需要4个字节的空间来存放,也就是32个二进制位。而这32个二进制位对于有符号整数来说最高位为符号位(为0则表示正数,为1则表示负数),所以有符号整数表示的范围在:-2,147,483,648 ~ 2,147,483,647;而对于无符号整数来说最高位并不是符号位,因为其本来就是用来表示非负整数的,所以表示范围在:0 ~ 4,294,967,295。值得补充的一点是:在32个二进制位中我们通常把最右边的那位称为最高位,最坐边的那位称为最低位。
整数有三种表示形式:原码、反码、补码。但值得注意的是:整数最终在内存中是以补码的形式存放的。并不是有些参考资料上说的:正整数是以原码的形式存放,负整数是以补码的形式存放。它这么说是为了方便记忆罢了,与真实情况是不符的。所以记住只要是整数,内存中存储的都是二进制的补码,只不过正数的原码、反码、补码相同,而负数的原、反、补不同,补码是要通过一系列计算才能得到。 而对于无符号整数来说,由于其全是正整数所以压根就不存在负数,所以原码、反码、补码和正数一样是相同的。
要得到负数的补码,首先就要先写出负数的原码(原码按照最高位为符号位来写),不拿写出 -1 的原码为:10000000000000000000000000000001;然后通过原码写出它的反码(原码的符号位不变其他位按位取反得到的就是反码),所以反码为:11111111111111111111111111111110;最后通过反码写出补码(反码加1就是补码),所以补码为:11111111111111111111111111111111 。值得注意的是printf()函数在打印整数时是通过读取内存中的补码,然后将其转换成原码的形式再打印的。简单来说就是printf()函数打印的是这个数的原码,记住了。
C语言中基本的位操作符有: 左移、右移、按位与、按位或、按位异或、取反。警告:对于移位操作,不要移动负数位,这个是标准未定义的!!!
左移是双目运算符 “ << ” ,运算符左边是移动对象,右边是左移位数(整形表达式)。左移时高位丢弃,低位补0。如下图所示的,正整数7向左移动一位后不难算出结果为14;负整数-7向左移动一位结果为-14。
右移运算符的使用方法与左移一样,不同的是移位方向相反。而且右移分为两种:算数右移、逻辑右移。算数右移:低位丢弃,高位补原符号位。逻辑右移:低位丢弃,高位补0。而在vs编译器中采用的是算数右移,如下图所示:
经过一段时间后你一定会惊讶的发现,左移操作符向左移动一位相当于乘上一个2 ^ 1,左移两位就相当于乘上一个2 ^ 2。而右移操作符右移一位相当于除上一个2 ^ 1。
按位取反是位运算符中唯一的一个单目运算符,运算符为 “ ~ ” 。其功能是:把目标的二进制位按位取反,即:使得每一位上的0变成1,1变成0。例子如下:
运算符 “ & ” 的作用是:把参见运算两个数所对应的二进制位分别进行“与”运算,即:两位同为“1”,结果才为“1”,否则为0。例子如下:
运算符 “ | ” 的作用是:把参见运算两个数所对应的二进制位分别进行“或”运算,即:两位同为“0”,结果才为“0”,否则为1。例子如下:
按位异或运算规则为:把参见运算两个数所对应的二进制位分别进行“异或”运算,相同为0,相异为1。例子如下:
通过上面的讲解相信大家已经对位操作符有所了解了,但大家有没有想过其实位操作符的对象可以是char、short、int、long、longlong型的,而这些类型的二进制位数是不同的,那该如何进行运算呢?遇到这种情况,系统会自动进行处理对齐操作,被称为:隐式类型的转换。该知识点我会在下几期博客中进行详细的讲解。
这份博客如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位点赞评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧。