在嵌入式开发中,程序通过发送一两个字节来控制某一设备,这“一两个字节”每一位都有其确切的含义,高级语言比较少涉及对某个变量的具体操作,C语言作为一个偏低层的语言,当然会有对变量每一位进行操作的方法。
一、数据的表示方法计算机存储补码,主要原因是计算机辨别"符号位"会让计算机的基础电路设计变得十分复杂[1]。因为正数需要使用一个状态用于表示0
,所以位数相同的数,正数比负数少一位。一般而言,int
是四个字节,即32位,可以表示的范围为-2^31~2^31-1
,如果有必要,可以使用内置宏打印上下界INT_MAX
INT_MIN
。
-
原码:是一种表示有符号整数的方法,它用数字的二进制表示,其中最高位是符号位。0表示正数,1表示负数。例如,+5的原码是0101,而-5的原码是1101。
-
反码:
- 对于正数:反码与原码相同。
- 对于负数:符号位保持为1,其余各位按位取反。例如,-5的原码是1101,其反码则是1010。
-
补码:
- 对于正数:补码与原码相同。
- 对于负数:取其反码后加1。继续使用-5为例,其反码是1010,加1后得到补码1011。
-
无符号数:这类数字没有符号位,因此也没有反码和补码的概念。当我们讨论一个数是否有符号,我们实际上是在询问其原码是否有符号位。
一个数据类型所占的比特数随着不同机器可能不同。
C++
只对类型的最小尺寸(比特数)进行了规定,像是51单片机int
就只有8位,long
则有32位。
事实上,简单的使用sizeof(type)
可以返回一个size_t
类型的字节数,通常C语言不对浮点型的位数进行限制,取而代之的是有效数字位数,不过,一般,float
4字节,double
和long double
都为8字节(51单片机也是)。
主要分为两类:
- 单目操作。取反
~
,移位 - 双目位操作。与
&
,或|
异或^
通过这两类即可完成对位的完全控制。关于位操作符号&
|
^
~
运算的结果,就不赘述了,查真值表便是。左移的结果超范围的仍然丢弃,无符号用
0
补齐,有符号,补0
还是1
取决于机器的具体实现。
为了实现对某个数的每个位的控制,需要借助掩码这一概念。掩码与原操作数的位操作组合,轻松查看、置位和复位。通常掩码和操作数的长度一样。
打开操作数的某一位,构造一个掩码,令要打开的位状态为1
,其余为0
,然后oper|=mask
; 关闭操作数的某一位,构造一个掩码,令要关闭的位状态为0
,其余为1
,然后oper&=mask
; 转置操作数的某一位,构造一个掩码,令要转置的位状态为1
,其余为0
,然后oper^=mask
; 查看操作数的某一位,构造一个掩码,令要查看的位状态位1
,其余为0
,然后oper&mask==mask
。
位字段使用类似于结构体的方式操作每一位,因为不同机器存放数据的方向可能不同,因此位字段难以移植。
五、C++ bitset库以二进制形式打印一个数,利用转换函数itoa
将一个数转换成指定进制的字符形式。对于C++
而言则可以通过定义一个bitset
对象完成二进制形式的数的操作。
越来越发现cppreference是个宝库,bitset目前有以下构造方法:
可以使用
unsigned long long
、string
或者C-string
对其进行初始化,同时还可以完成几乎所有的位操作,如前面提到的置位、复位等,还有位运算&
|
^
~
,左右移动,甚至刷题的时候,类似于统计
1
个数的题目直接用count()
就可以完成了,自己也在实际的中使用到了bitset
,让我感觉不算是特别方便,主要原因是大多数底层接口都用基本数字类型的接口,无论是收发还是要转来转去,还不如直接使用位操作完事。
可以利用bitset二进制形式打印一个数:
std::bitset digit(4396);
std::cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?