数据的位数和位操作

数据的位数和位操作在嵌入式开发中 程序通过发送一两个字节来控制某一设备 这 一两个字节 每一位都有其确切的含义 高级语言比较少涉及对某个变量的具体操作 C 语言作为一个偏低层的语言 当然会有对变量每一位进行操作的方法 一 数据的表示方法 计算机存储补码 主要原因是计算机辨别 符号位

大家好,我是讯享网,很高兴认识大家。

在嵌入式开发中,程序通过发送一两个字节来控制某一设备,这“一两个字节”每一位都有其确切的含义,高级语言比较少涉及对某个变量的具体操作,C语言作为一个偏低层的语言,当然会有对变量每一位进行操作的方法。

一、数据的表示方法

计算机存储补码,主要原因是计算机辨别"符号位"会让计算机的基础电路设计变得十分复杂[1]。因为正数需要使用一个状态用于表示0,所以位数相同的数,正数比负数少一位。一般而言,int是四个字节,即32位,可以表示的范围为-2^31~2^31-1,如果有必要,可以使用内置宏打印上下界INT_MAX INT_MIN

  1. 原码:是一种表示有符号整数的方法,它用数字的二进制表示,其中最高位是符号位。0表示正数,1表示负数。例如,+5的原码是0101,而-5的原码是1101。
  2. 反码
    • 对于正数:反码与原码相同。
    • 对于负数:符号位保持为1,其余各位按位取反。例如,-5的原码是1101,其反码则是1010。
  3. 补码
    • 对于正数:补码与原码相同。
    • 对于负数:取其反码后加1。继续使用-5为例,其反码是1010,加1后得到补码1011。
  4. 无符号数:这类数字没有符号位,因此也没有反码和补码的概念。当我们讨论一个数是否有符号,我们实际上是在询问其原码是否有符号位。

1
讯享网
一个数据类型所占的比特数随着不同机器可能不同。C++只对类型的最小尺寸(比特数)进行了规定,像是51单片机int就只有8位,long则有32位。

类型 含义 最小尺寸
bool 布尔类型 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode字符 16位
char32_t Unicode字符 32位
short 短整型 16位
int 整型 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点型 6位有效数字
double 双精度浮点型 10位有效数字
long double 扩展精度浮点型 10位有效数字

事实上,简单的使用sizeof(type)可以返回一个size_t类型的字节数,通常C语言不对浮点型的位数进行限制,取而代之的是有效数字位数,不过,一般,float4字节,doublelong double都为8字节(51单片机也是)。

二、位操作可以有多少种操作?

主要分为两类:

  • 单目操作。取反~,移位<<>>
  • 双目位操作。与&,或|异或^

通过这两类即可完成对位的完全控制。关于位操作符号& | ^ ~运算的结果,就不赘述了,查真值表便是。左移<<将其左侧的操作数每位向左移动一位,最右边的数用0补,超出范围的丢弃;右移>>的结果超范围的仍然丢弃,无符号用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对象完成二进制形式的数的操作。

2
越来越发现cppreference是个宝库,bitset目前有以下构造方法:
3
可以使用unsigned long longstring或者C-string对其进行初始化,同时还可以完成几乎所有的位操作,如前面提到的置位、复位等,还有位运算& | ^ ~,左右移动<< >>,甚至刷题的时候,类似于统计1个数的题目直接用count()就可以完成了,自己也在实际的中使用到了bitset,让我感觉不算是特别方便,主要原因是大多数底层接口都用基本数字类型的接口,无论是收发还是要转来转去,还不如直接使用位操作完事。

可以利用bitset二进制形式打印一个数:

std::bitset<64> digit(4396); std::cout<<digit<<std::endl; 

讯享网

在这里插入图片描述
实用的宏:

讯享网#define bitset(byte,nbit) ((byte)|=(1<<(nbit))) #define bitclc(byte,nbit) ((byte) &= ~(1<<(nbit))) #define bitflip(byte,nbit) ((byte) ^= (1<<(nbit))) #define bitcheck(byte,nbit) ((byte) & (1<<(nbit))) 

BCD码

十进制数可以转换成二进制数,方法是通过“除二取余反向书写”,计算机运算默认的操作数都是二进制数,比如你要传输一个十进制数,肯定要先转成二进制,如果用传统的除二取余和乘二取整进行真实的转化(浮点运算),设计起来太复杂,如果单纯为了传输而不需要对数字进行加减等处理的话,搞个四位对一位的编码最省力,很容易用一个四输入一输出的编码器电路实现,传过去之后再用译码器转成十进制就行了[2]。


[1]啊窝额.原码, 补码, 反码详解[EB/OL].https://zhuanlan.zhihu.com/p/?utm_source=zhihu&utm_medium=social&utm_oi=,2020-02-14.
[2]https://www.zhihu.com/question//answer/
[3] https://www.codementor.io/@hbendali/c-c-macro-bit-operations-ztrat0et6

增加了bitset使用例子和简便宏

小讯
上一篇 2025-01-09 15:40
下一篇 2025-03-26 09:36

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/26108.html