常见问题

本文回答经常出现的关于 bitproto 的问题

bitproto 是否和大小端有关?

是的,bitproto 是大小端相关的,目前它只支持小端系统。在数据序列化方面,大小端一直是一个问题。但是对于大部分的 CPU 处理器 (包括 x86, armv7, armv8 和大多数的 arm cortex-m mcu) 都是小端的,或者默认设置为小端的。目前还没有计划来支持大端系统,也没有计划做大小端无关的序列化支持。

和位域相比有好处?

位域 是 C 语言标准中的一个功能,不过几乎所有关于位域的事情都是实现相关的,包括它们的大小、内存布局。除去大小端问题之外,位域在内存中的排序不止只和系统有关,还和编译器实现有关。

此外,bitproto 仍然需要支持 Python 和 Go 语言,它们是没有位域这种功能的。如果我们使用位域来交换数据,那么非 C 语言的用户就需要自己来手工编写编码机制了。

非常有趣地指出下,如果我们设置位域的结构体的空隙为零,bitproto 的编码实际上会和它一致。举例来说,下面的 C 程序中获得的字符串 s 和下面的 bitproto 消息 Data 的编码后的数据是一样的:

struct Data {
    uint8_t a : 3;
    uint8_t b : 3;
    uint8_t c : 5;
    uint8_t d : 7;
} __attribute__((packed, aligned(1))); // this line matters

struct Data d = {1, 5, 28, 70};
unsigned char *s = (unsigned char *)(&d);
message Data {
   uint3 a = 1
   uint3 b = 2
   uint5 c = 3
   uint7 d = 4
}

即便如此,仍然推荐使用 bitproto 而不是 bitfields。bitproto 是编译器无关的,跨多个语言的,并且可以支持扩展性协议设计。

使用比特级别的整数是安全的吗?

如果在运行时给一个无符号整数赋值一个数字后导致溢出怎么办?比如说,如果我要赋值给一个 uint3 类型一个数字 9

对于枚举的情况,是非常安全的,bitproto 的编译器会在编译期检查枚举值是否溢出。

enum Color : uint3 {
    // The bitproto compiler will report error here.
    COLOR_OVERFLOW = 18
}

不过对于字面量形式使用 uint{n} 的情况,则需要自己来保证,bitproto 不会在编解码的运行时检查数值溢出情况。

message Data {
    uint3 value = 1
}
struct Data d = {};
// No error will be reported here.
// Having to ensure it's safe by yourself.
d.value = 18;