数组实现协议缓冲区编码是将结构化数据按固定规则转为字节序列,如计算器请求x、y(int32)、op(char)共9字节,小端序存入uint8_t buf[9],通过手写serialize_calc和deserialize_calc函数完成序列化与反序列化。

用数组实现协议缓冲区编码,核心是把结构化数据按固定规则转成字节序列,再靠同样规则还原。它不依赖第三方库,适合嵌入式、教学或轻量通信场景,关键在于手动管理字段顺序、长度和类型标识。
明确协议格式与数组布局
先定义你要传输的数据结构,比如一个计算器请求:x(int32)、y(int32)、op(char,1字节)。总长 = 4 + 4 + 1 = 9 字节。数组就声明为 uint8_t buf[9]。
约定好每个字段在数组中的起始偏移:
- x 占前 4 字节:buf[0]~buf[3],按小端序存(如 x=1 → [0x01, 0x00, 0x00, 0x00])
- y 占中间 4 字节:buf[4]~buf[7]
- op 占最后 1 字节:buf[8],例如 '+' 存为 0x2B
手写序列化函数(C语言示例)
把变量填进数组,注意字节序和类型截断:
void serialize_calc(int32_t x, int32_t y, char op, uint8_t* buf) {
// 写 x(小端)
buf[0] = x & 0xFF;
buf[1] = (x >> 8) & 0xFF;
buf[2] = (x >> 16) & 0xFF;
buf[3] = (x >> 24) & 0xFF;
<pre class="brush:php;toolbar:false;">// 写 y
buf[4] = y & 0xFF;
buf[5] = (y >> 8) & 0xFF;
buf[6] = (y >> 16) & 0xFF;
buf[7] = (y >> 24) & 0xFF;
// 写 op
buf[8] = (uint8_t)op;}
调用方式:serialize_calc(10, 3, '+', buf); → buf 内容即为可发送的 9 字节原始数据。
手写反序列化函数
从数组中按相同偏移和顺序提取字段:
void deserialize_calc(const uint8_t* buf, int32_t* x, int32_t* y, char* op) {
// 读 x
*x = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
<pre class="brush:php;toolbar:false;">// 读 y
*y = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
// 读 op
*op = (char)buf[8];}
确保两端使用完全一致的字节序和字段布局,否则会解析错乱。
实战中需处理的关键细节
纯数组编码看似简单,但实际部署时必须考虑:
- 对齐与填充:避免结构体直接 memcpy,因编译器可能自动加 padding;始终按字节偏移操作
-
大小端一致性:跨平台通信时,统一用网络字节序(大端),可用
htonl()/ntohl()转换 - 边界检查:传入 buf 长度不足 9 时,应提前校验,防止越界写
- 字符串字段:若含字符串,需约定长度(如固定 32 字节)或加长度前缀(如 1 字节 len + 最多 255 字符)
- 版本兼容:后续加字段时,可在开头加 1 字节 version,接收方按 version 分支解析
这种数组级编码是理解 protobuf、JSON 等高级序列化的底层基础——它们本质也是把数据映射为字节流,只是自动处理了类型、嵌套、扩展等逻辑。

















