用一个字节保存8个条件

181 阅读3分钟
  1. 背景

    两年前,看到公司的C语言大佬用0x2,0x4等16进制表示单片机指令,当时也没有深究,一是学不会,二是用不到。然后最近转做c++后端,看前辈写的代码,常量用了很多16进制,判断也用了很多位运算,顿感疑惑,仔细研究,才发现其中的深意。

  2. 场景

平时做web,前后端交互,用得最多的可能是json。用tcp传输,则可以直接传输内存数据。

转变一下思路,像比较简单的指令和条件,其实可以直接用计算机最小的存储单位(位)来表示,即,0表示false,1表示true。

这样以来,一个字节(8位)就可以存放8个条件,一串完整的条件就可以表示为 00101100,如果是只有两个选项的,可以直接用一个位表示,如果是多选,可以用一个位表示一个选项。那这样表示的数据怎么进行条件判断呢,用与运算,比如00000010 & 01,与运算的规则为:当同一位的两个数都为1时,结果为1,这里因为前后两个数的1并没有在同一位,所以结果为0,0就代表未满足条件。如果是10 & 10,结果就会是10,结果不为0,进行if判断的时候,结果就会为true。

贴一下位运算的资料 位运算-菜鸟教程

需要注意的是,这里所有的表示都是2进制,实际判断的时候可能会用到10进制或者16进制0b10 --> 0x2 --> 2,0b10000 -->0x10 -->16

下面进行代码演示。  
后端判断
```c++
typedef unsigned char BYTE;
void Analysis(BYTE conditions)
{
    unsigned char nums[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
    
    for (size_t i = 0; i < 8; i++)
    {
        if (nums[i] & conditions)
            cout << "满足条件" << i << endl;
    }
}
```
前端如何构造这样一个表示n个条件的数据呢?
```c++
BYTE GenerateData()
{
    BYTE data = 0;
    if (condition0)
        data += 0x1;
    if (condition1)
        data += 0x2;
    if (condition2)
        data += 0x4;
    return data;
}
```
模拟实际处理
```c++
int main()
{
    BYTE data = GenerateData();
    Analysis(data);
}
```
实际输出结果
```console
满足条件0
满足条件1
满足条件2
```
可以看到控制台进行了准确的输出,而实际传输只用了一个字节,不再需要冗长的json。

3.这样做有什么好处?

  • 节省内存
    现在只用了1个字节,如果是json字符串,可能需要几十个字节,如果序列化成map类型,需要开辟的空间更多。并发上去了之后,开销还会乘以N倍,而且这不光是节省了一个函数处理的内存,更多的是传递一种思想->如何节省内存,如果都这样用,整个项目下来节省的内存应该还是比较可观。
  • 节省计算时间
    如果传json,再序列化成map类型,中间需要字符解析,需要map存、取,如果数据再多点,可能还需要map扩容,而现在只需要与运算简单判断一下,计算时间和==差不多,远比用json+map的计算时间短。
  • 节省传输时间?
    我之前在想,如果传输的数据量小了,中间网络传输的时间会不会变短,查了一下协议,一个以太数据包的大概能负载1400字节左右,所以在这个范围内的数据差不多都是一次发包,传字符串和传一个字节,速度应该是一致的。这里贴一下关于协议的文章。TCP协议简介-阮一峰
  1. 放在最后
    之前一直使用python,所以并未过多关注内存,使用c++之后,对内存和位运算的理解明显深了不少,理解底层也更有利于代码的高效和低开销。本文章仅作为学习整理之用,如有错误,还请多多指教。