如何在C语言中实现类似Python struct模块的整数与字节数组互转?
在C语言中实现类似Python struct的打包/解包功能
Python的struct模块核心是完成整数与固定长度大端字节序列的双向转换,在C语言中可以通过手动位运算或标准库函数实现完全一致的功能,以下是针对你示例中>I(大端无符号32位整数)和>Q(大端无符号64位整数)场景的具体实现:
1. 打包(整数转大端字节串)
方法一:手动位运算(跨平台通用)
直接提取整数的每个字节,按大端高位在前的顺序存入数组:
#include <stdint.h> #include <string.h> // 对应Python struct.pack('>I', num) void pack_uint32_be(uint32_t num, uint8_t *out_bytes) { out_bytes[0] = (num >> 24) & 0xFF; out_bytes[1] = (num >> 16) & 0xFF; out_bytes[2] = (num >> 8) & 0xFF; out_bytes[3] = num & 0xFF; } // 对应Python struct.pack('>Q', num) void pack_uint64_be(uint64_t num, uint8_t *out_bytes) { out_bytes[0] = (num >> 56) & 0xFF; out_bytes[1] = (num >> 48) & 0xFF; out_bytes[2] = (num >> 40) & 0xFF; out_bytes[3] = (num >> 32) & 0xFF; out_bytes[4] = (num >> 24) & 0xFF; out_bytes[5] = (num >> 16) & 0xFF; out_bytes[6] = (num >> 8) & 0xFF; out_bytes[7] = num & 0xFF; }
方法二:利用标准库字节序转换函数
多数系统提供htonl()(32位主机序转网络大端序)、htonll()(64位主机序转网络大端序)函数,转换后直接复制字节即可:
#include <stdint.h> #include <arpa/inet.h> // Linux/macOS用,Windows需替换为winsock2.h #include <string.h> void pack_uint32_be_std(uint32_t num, uint8_t *out_bytes) { uint32_t network_num = htonl(num); memcpy(out_bytes, &network_num, sizeof(uint32_t)); } void pack_uint64_be_std(uint64_t num, uint8_t *out_bytes) { uint64_t network_num = htonll(num); memcpy(out_bytes, &network_num, sizeof(uint64_t)); }
2. 解包(大端字节串转整数)
方法一:手动位运算(跨平台通用)
按大端顺序读取字节数组的每个字节,组合成目标整数:
#include <stdint.h> // 对应Python struct.unpack('>I', bytes) uint32_t unpack_uint32_be(const uint8_t *in_bytes) { return ((uint32_t)in_bytes[0] << 24) | ((uint32_t)in_bytes[1] << 16) | ((uint32_t)in_bytes[2] << 8) | in_bytes[3]; } // 对应Python struct.unpack('>Q', bytes) uint64_t unpack_uint64_be(const uint8_t *in_bytes) { return ((uint64_t)in_bytes[0] << 56) | ((uint64_t)in_bytes[1] << 48) | ((uint64_t)in_bytes[2] << 40) | ((uint64_t)in_bytes[3] << 32) | ((uint64_t)in_bytes[4] << 24) | ((uint64_t)in_bytes[5] << 16) | ((uint64_t)in_bytes[6] << 8) | in_bytes[7]; }
方法二:利用标准库字节序转换函数
先将字节数组复制到整数变量,再用ntohl()/ntohll()转为主机序:
#include <stdint.h> #include <arpa/inet.h> #include <string.h> uint32_t unpack_uint32_be_std(const uint8_t *in_bytes) { uint32_t network_num; memcpy(&network_num, in_bytes, sizeof(uint32_t)); return ntohl(network_num); } uint64_t unpack_uint64_be_std(const uint8_t *in_bytes) { uint64_t network_num; memcpy(&network_num, in_bytes, sizeof(uint64_t)); return ntohll(network_num); }
测试示例
以下代码完全对应你给出的Python示例,可直接验证功能一致性:
#include <stdio.h> int main() { // 测试32位整数打包/解包 uint32_t num32 = 13934; uint8_t pack32[4]; pack_uint32_be(num32, pack32); printf("Packed uint32: 0x%02X 0x%02X 0x%02X 0x%02X\n", pack32[0], pack32[1], pack32[2], pack32[3]); uint8_t unpack32_data[] = {0x00, 0x00, 0x36, 0x6E}; uint32_t unpacked32 = unpack_uint32_be(unpack32_data); printf("Unpacked uint32: %u\n", unpacked32); // 测试64位整数打包/解包 uint64_t num64 = 12345678901234567890ULL; uint8_t pack64[8]; pack_uint64_be(num64, pack64); printf("Packed uint64: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", pack64[0], pack64[1], pack64[2], pack64[3], pack64[4], pack64[5], pack64[6], pack64[7]); uint8_t unpack64_data[] = {0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD2}; uint64_t unpacked64 = unpack_uint64_be(unpack64_data); printf("Unpacked uint64: %llu\n", unpacked64); return 0; }
注意事项
- Windows平台使用标准库函数时,需包含
winsock2.h并链接ws2_32.lib。 - 手动位运算的方法完全不受系统字节序影响,适合需要严格控制字节顺序的场景。
内容的提问来源于stack exchange,提问作者S-N
相关产品推荐
相关产品推荐

