C语言中unsigned short与byte数组互转实现需求(SPI传输用)
How to Convert
unsigned short Array to uint8_t (Byte) Array and Back for SPI Transmission 没问题,要实现SPI传输中unsigned short数组和字节数组的双向转换且不丢失数据,核心是处理好字节序(因为SPI是字节流,两端必须用相同的字节规则拆分/组合),同时保证缓冲区大小足够。
先说明:你示例里的函数名charArrayToByteArray和arrayByteToCharArray有点误导(我们处理的是unsigned short而非char),我会用更清晰的命名,你可以根据需求改名。
发送端:Convert unsigned short Array to uint8_t Array
unsigned short通常占2字节,所以转换后的字节数组长度是原数组长度的2倍。这里提供两种实现方式,推荐第一种(调用者提供缓冲区),避免内存泄漏风险:
方式1:调用者提供目标缓冲区(推荐)
这种方式不需要动态分配内存,更安全可控:
#include <stdint.h> // 将unsigned short数组转换为uint8_t字节数组 // 参数说明: // - src: 源unsigned short数组 // - dest: 目标字节数组,需确保大小 ≥ 2 * src_len 字节 // - src_len: 源数组的元素个数 void ushortArrayToByteArray(const unsigned short *src, uint8_t *dest, size_t src_len) { for (size_t i = 0; i < src_len; i++) { // 这里采用**大端序**(高位字节在前),SPI通信常用此格式,跨平台兼容性好 // 如果需要小端序,交换下面两行代码即可 dest[2 * i] = (uint8_t)(src[i] >> 8); // 提取高8位 dest[2 * i + 1] = (uint8_t)(src[i] & 0xFF); // 提取低8位 } }
使用示例(对应你的发送端代码):
unsigned short array[10] = {65000, 0, 6000, 15000, 100, 50, 1000, 10, 5000, 2000}; uint8_t byte_buf[20]; // 10个unsigned short → 20字节,必须保证缓冲区足够 ushortArrayToByteArray(array, byte_buf, 10); send(byte_buf, sizeof(byte_buf)); // 发送20字节数据
方式2:动态分配内存(需手动释放)
如果不想提前固定缓冲区大小,可以动态分配,但一定要记得用free()释放内存:
#include <stdint.h> #include <stdlib.h> // 动态分配内存转换unsigned short数组为字节数组,返回NULL表示内存分配失败 uint8_t* ushortArrayToByteArray(const unsigned short *src, size_t src_len) { uint8_t *dest = malloc(2 * src_len); if (dest == NULL) { return NULL; } for (size_t i = 0; i < src_len; i++) { dest[2 * i] = (uint8_t)(src[i] >> 8); dest[2 * i + 1] = (uint8_t)(src[i] & 0xFF); } return dest; }
使用示例:
unsigned short array[10] = {65000, 0, 6000, 15000, 100, 50, 1000, 10, 5000, 2000}; uint8_t *data = ushortArrayToByteArray(array, 10); if (data != NULL) { send(data, 20); // 发送20字节 free(data); // 必须释放内存,避免泄漏 }
接收端:Convert uint8_t Array Back to unsigned short Array
接收端的转换必须和发送端的字节序保持一致(大端/小端),否则会得到错误的数据:
方式1:调用者提供目标缓冲区
#include <stdint.h> // 将字节数组转换为unsigned short数组 // 参数说明: // - src: 源字节数组 // - dest: 目标unsigned short数组,需确保大小 ≥ src_len / 2 个元素 // - src_len: 源字节数组的长度(必须是偶数,否则无法完整转换) void byteArrayToUshortArray(const uint8_t *src, unsigned short *dest, size_t src_len) { if (src_len % 2 != 0) { return; // 字节数为奇数,无法完整转换,可根据需求添加错误处理 } size_t dest_len = src_len / 2; for (size_t i = 0; i < dest_len; i++) { // 大端序还原,和发送端逻辑对应 dest[i] = (unsigned short)src[2 * i] << 8; // 高8位左移 dest[i] |= (unsigned short)src[2 * i + 1]; // 或上低8位 } }
使用示例(对应你的接收端代码):
uint8_t buf[20]; uint8_t len = sizeof(buf); receive(buf, &len); unsigned short array[10]; byteArrayToUshortArray(buf, array, len); // 现在array中就是还原后的原始数据
方式2:动态分配内存
#include <stdint.h> #include <stdlib.h> // 动态分配内存转换字节数组为unsigned short数组,返回NULL表示错误 unsigned short* byteArrayToUshortArray(const uint8_t *src, size_t src_len) { if (src_len % 2 != 0) { return NULL; // 字节数为奇数,无法转换 } size_t dest_len = src_len / 2; unsigned short *dest = malloc(dest_len * sizeof(unsigned short)); if (dest == NULL) { return NULL; } for (size_t i = 0; i < dest_len; i++) { dest[i] = (unsigned short)src[2 * i] << 8 | (unsigned short)src[2 * i + 1]; } return dest; }
使用示例:
uint8_t buf[20]; uint8_t len = sizeof(buf); receive(buf, &len); unsigned short *array = byteArrayToUshortArray(buf, len); if (array != NULL) { // 使用还原后的array数据 free(array); // 记得释放内存 }
关键注意事项
- 字节序一致性:发送端和接收端必须使用完全相同的字节序(大端或小端)。大端序是SPI通信的通用选择,跨平台兼容性更好;如果你的系统是小端序(比如x86、多数ARM),也可以用小端,但两端必须统一。
- 缓冲区大小:转换后的字节数组长度是原
unsigned short数组长度的2倍,接收时要确保缓冲区能容纳足够的字节,否则会截断数据导致还原失败。 - 内存管理:如果使用动态分配内存的方式,一定要记得调用
free()释放,避免内存泄漏。 - 数据完整性:这种转换方式只是拆分/组合字节,不会改变
unsigned short的数值,所以完全不会损失数据(只要传输过程中没有丢包)。
内容的提问来源于stack exchange,提问作者Tibbe
相关产品推荐
相关产品推荐

