google protocol buffer 编码详解(1)

 

google protocol buffer 编码详解(1)

分类: 技术类   73人阅读  评论(0)  收藏  举报

在进行前,需要阅读下基础知识

基本知识:https://developers.google.com/protocol-buffers/docs/encoding

中文译文:http://www.wuzesheng.com/?p=1258


1. 从最简单的开始

 message Info

{
        optional int32 m_iValue = 1;

}


Test::Info stInfo;
stInfo.set_m_ivalue(2);


输出:

buf size:2, content:
Bin: 0000100000000010
Hex: 0802


解释: 00001000 (field number 1 左移3位) 00000010(2)


2. optional 定义的成员,如果没有设置值,那么不会被编码

 message Info

{
       optional int32 m_iValue = 1;

}


Test::Info stInfo;

不设置成员值

buf size:0, content:
Bin: 
Hex: 


3.  required vs optional

message Info

{
        required int32 m_iValue = 1;

}


设置成员值和不设置成员值,输入跟上面的optional是一样的,难道在c++的实现下,required和optional没区别?

diff查看2者生成的文件,cc文件区别如下:

optional.cc

bool Info::IsInitialized() const {


  return true;
}


void protobuf_AddDesc_test_2eproto() {
  static bool already_here = false;
  if (already_here) return;
  already_here = true;
  GOOGLE_PROTOBUF_VERIFY_VERSION;


  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
    "\n\ntest.proto\022\004Test\"\030\n\004Info\022\020\n\010m_iValue\030\001"
    " \001(\005", 44);//这里是001
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
    "test.proto", &protobuf_RegisterTypes);
  Info::default_instance_ = new Info();
  Info::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_test_2eproto);
}


required.cc

bool Info::IsInitialized() const {
  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;//多了这样一行


  return true;
}

void protobuf_AddDesc_test_2eproto() {
  static bool already_here = false;
  if (already_here) return;
  already_here = true;
  GOOGLE_PROTOBUF_VERIFY_VERSION;


  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
    "\n\ntest.proto\022\004Test\"\030\n\004Info\022\020\n\010m_iValue\030\001"
    " \002(\005", 44);//这里是002
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
    "test.proto", &protobuf_RegisterTypes);
  Info::default_instance_ = new Info();
  Info::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_test_2eproto);
}


也就是说在required生成的文件中是有生成函数IsInitialized()来检测成员是否赋值,但是在真正serialize的时候并没有调用该函数去检查是否设置成员值。难道是需要程序员自己来主动调用该函数进行检查。


4. 负数的编码 int vs sint

message Info

{
        optional int32 m_iValue = 1;
}


Test::Info stInfo;

stInfo.set_m_ivalue(-1);

output:

buf size:11, content:
Bin: 0000100011111111111111111111111111111111111111111111111111111111111111111111111100000001
Hex: 08ffffffffffffffffff01


解释:64位的int(为什么是64位,不是指明32位吗?)-1,编码为8个f,因为pb每个byte需要一位来指明编码是否结束,每个byte的实际有效位只有7位,所以编码-1,需要10个byte(64除以7=9,余1)。综合起来,那么编码-1就需要11个byte


Test::Info stInfo;

stInfo.set_m_ivalue(-3);


buf size:11, content:
Bin: 0000100011111101111111111111111111111111111111111111111111111111111111111111111100000001
Hex: 08fdffffffffffffffff01

解释:-3的编码为fd+7个f,其它的解释同上


message Info
{
        optional sint32 m_iValue = 1;
}

 Test::Info stInfo;
 stInfo.set_m_ivalue(-1);


buf size:2, content:
Bin: 0000100000000001
Hex: 0801

解释:sint使用zig-zags来编码 (00001000是field number 偏移3位) 00000001为-1的zig-zags编码


查看评论

  暂无评论

* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值