字节序

bitproto 的编码格式在所有平台上都是 小端序 (little-endian):编码后字节序列中索引最低的字节存放字段的最低有效位。这是编码格式的固定属性,与运行编码器或解码器的机器无关 —— 字节序不同的两端始终可以互通。

各语言的支持情况

宿主机 CPU 是否为大端序只对 C 有影响,因为只有 C 会直接读取整数字段的原始内存字节。Python 和 Go 是对整数的 做移位和掩码运算,这种方式天然与字节序无关。

目标语言

比特如何搬运

大端序主机

Python

对 Python 整数做数值运算

始终正确

Go

对定型字段做数值移位

始终正确

C(标准模式)

lib/c 运行库

正确

C(优化模式)

生成的比特拷贝语句

正确

因此 Go 和 Python 不需要做任何特殊处理。本页接下来的内容都是关于 C 的。

C 标准模式

The C library (lib/c/bitproto.c) detects a big-endian host automatically (via __BYTE_ORDER__ for GCC/Clang, __ARM_BIG_ENDIAN for ACLE-compatible Arm toolchains such as TI Arm Clang, __big_endian__ for legacy TI ARM CGT, __BIG_ENDIAN__ for other toolchains, and __LITTLE_ENDIAN__ == 0 for IAR) and selects an endian-neutral code path. You may also force it by defining BP_BIG_ENDIAN when compiling the library, for toolchains that expose none of these macros:

$ cc -DBP_BIG_ENDIAN -c bitproto.c

在小端序主机上,运行库逐字节保持不变,因此对常见的目标平台没有任何性能影响。

C 优化模式

优化模式 会生成直接的比特拷贝语句,通过整数字段的内存字节来读写它们。为了在小端序和大端序主机上都保持正确,bitproto 默认会生成两份等价的代码路径,并用一个预处理宏来区分:

#ifndef BP_BIG_ENDIAN
    // fast byte-pointer path (little-endian hosts)
#else
    // portable bit-shift path (big-endian hosts)
#endif

A big-endian host is auto-detected (via __BYTE_ORDER__ for GCC/Clang, __ARM_BIG_ENDIAN for ACLE-compatible Arm toolchains such as TI Arm Clang, __big_endian__ for legacy TI ARM CGT, __BIG_ENDIAN__ for other toolchains, and __LITTLE_ENDIAN__ == 0 for IAR); you may also force the big-endian path by defining BP_BIG_ENDIAN when compiling the generated code. The little-endian path is identical to earlier bitproto releases, so there is no performance change on little-endian targets — only the generated source is a little larger.

--endian 选项

如果你已经知道目标平台的字节序,可以用 --endian 选项去掉用不到的那份代码路径,从而缩小生成的源码(仅在优化模式下有效):

# default: both paths, host auto-detected
$ bitproto c example.bitproto -O

# only the fast little-endian path (smaller output, no big-endian support)
$ bitproto c example.bitproto -O --endian=little

# only the portable big-endian path
$ bitproto c example.bitproto -O --endian=big

--endian 只影响优化模式下的 C/C++ 代码。它不会影响编码格式,也不影响 Go 和 Python。