protobuf int类型变长存储 varint32 和 varint64

VarInt32 编码

VarInt32 (vary int 32),即:长度可变的 32 为整型类型。一般来说,int 类型的长度固定为 32 字节。但 VarInt32 类型的数据长度是不固定的,VarInt32 中每个字节的最高位有特殊的含义。如果最高位为 1 代表下一个字节也是该数字的一部分。因此,表示一个整型数字最少用 1 个字节,最多用 5 个字节表示。如果某个系统中大部分数字需要 >= 4 字节才能表示,那其实并不适合用 VarInt32 来编码。下面以一个例子解释 VarInt32 的编码方式:

以 129 为例,它的二进制为 1000 0001 。
由于每个字节最高位用于特殊标记,因此只能有 7 位存储数据。
第一个字节存储最后 7 位 (000 0001),但并没有存下所有的比特,因此最高位置位 1,剩下的部分用后续字节表示。所以,第一个字节为:1000 0001
第二个字节只存储一个比特位即可,因此最高位为 0 ,所以,第二个字节为:0000 0001
这样,我们就不必用 4 字节的整型存储 129 ,可以节省存储空间
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <bitset>

void GetBit(char* dst, uint32_t v, int* begin) {
  int32_t a = v;
  while(v > 0) {
    if ((v & 0x1) == 0x1) {
      dst[*begin] = '1';
    } else {
      dst[*begin] = '0';
    }
    *begin = *begin + 1;
    v = v >> 1;
  }
  if (a == 0) {
    dst[*begin] = '0';
    *begin = *begin + 1;
  }
}

// 编码
char* EncodeVarint32(uint32_t v, int& len) {
  char* dst = new char[100];
  std::memset(dst, 0, 100);
  int begin =0;
  char* b = dst;
  while(true) { 
    if((v & ~0x7F) == 0) { // v 与 10000000, 代表只有低7位有值,因此只需1个字节即可完成编码
      GetBit(b, v, &begin);
      break;
    }  else {
      代表编码不止一个字节,value & 0x7f 只取低 7 位,
      // 与 0x80 进行按位或(|)运算为了将最高位置位 1 ,代表后续字节也是改数字的一部分
      uint32_t t = (uint32_t)((v & 0x7F) | 0x80);  
      GetBit(b, t, &begin);
      v  = v >> 7;
    }
  }
  len = begin;
  char* revers = new char[100];
  for(int i=len-1; i >= 0; i--) {
    revers[len -1 -i] = dst[i];
  }
  for(int i= len; i <100; i++) {
    revers[i] = '\0';
  }
  return revers;
}

int main () {
  uint32_t num = 16;
  int len = 0;
  char* result = EncodeVarint32(num, len);
  std::cout << num << " : " << result << " len: " << len << std::endl;
  
  num = 129;
  result = EncodeVarint32(num, len);
  std::cout << num << " : " << result << " len: " << len << std::endl;

  num = __UINT32_MAX__;
  result = EncodeVarint32(num, len);
  std::cout << num << " : " << result << " len: " << len << std::endl;
  return 0;
}

输出:

16 : 10000 len: 5
129 : 110000001 len: 9
4294967295 : 111111111111111111111111111111111111 len: 36

主要介绍了 VarInt32 编解码,VarInt32 表示一个整型数字最少用 1 个字节, 最多用 5 个字节。所以在传输数字大部分都比较小的场景下适合使用。当然,我们也可以用 VarInt64 来表示长整型的数字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝鲸123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值