如何在C语言中实现C++模板式的通用EEPROM读写函数?
如何在C语言中实现通用的EEPROM读写函数?
我在C++里用模板轻松实现了支持任意类型的EEPROM读写通用函数:
template<class T> int EEPROM_put(int ee, const T& value) { const byte* p = (const byte*)(const void*)&value; unsigned int i; for (i = 0; i < sizeof(value); i++) foo(ee++, *p++); return i; } template<class T> int EEPROM_get(int ee, T& value) { byte* p = (byte*)(void*)&value; unsigned int i; for (i = 0; i < sizeof(value); i++) *p++ = foo(ee++); return i; }
但自己写的C语言版本只能支持u16类型,而且EEPROM_get函数还没法正常工作:
int EEPROM_put(int ee, u16 value){ const u8* p = (const u8*)(const void*)&value; unsigned int i; for (i = 0; i < sizeof(value); i++) { eeprom_write_1byte(ee++, *p++); Delay_Ms(10); } return i; } int EEPROM_get(int ee, u16 value) { u8* p = (u8*)(void*)&value; unsigned int i; for (i = 0; i < sizeof(value); i++) { *p++ = eeprom_read_1byte(ee++); Delay_Ms(10); } return i; }
想问下有没有办法在C语言里实现和C++模板等效的通用EEPROM读写函数?
解决方案
C语言没有模板特性,但可以通过void指针+传递类型大小实现通用化,先修复你现有EEPROM_get的问题,再逐步实现通用版本:
1. 修复u16版本的EEPROM_get
你的EEPROM_get参数是传值,修改的只是函数内部的副本,外部变量完全不会更新。必须改成传指针:
int EEPROM_get_u16(int ee, u16 *value) { u8* p = (u8*)(void*)value; unsigned int i; for (i = 0; i < sizeof(*value); i++) { *p++ = eeprom_read_1byte(ee++); Delay_Ms(10); } return i; }
调用时要传变量地址:EEPROM_get_u16(0x00, &my_u16_var);
2. 实现通用读写函数
利用C语言void*可指向任意类型的特性,搭配字节大小参数,就能写出支持所有类型的通用函数:
通用写函数
int EEPROM_put_generic(int ee, const void *value, size_t size) { const u8* p = (const u8*)value; unsigned int i; for (i = 0; i < size; i++) { eeprom_write_1byte(ee++, *p++); Delay_Ms(10); } return i; }
调用示例:
// 写入u16类型 u16 num = 0x1234; EEPROM_put_generic(0x00, &num, sizeof(num)); // 写入结构体类型 typedef struct { float temp; u8 status; } SensorData; SensorData data = {25.5, 0x01}; EEPROM_put_generic(0x02, &data, sizeof(data));
通用读函数
int EEPROM_get_generic(int ee, void *value, size_t size) { u8* p = (u8*)value; unsigned int i; for (i = 0; i < size; i++) { *p++ = eeprom_read_1byte(ee++); Delay_Ms(10); } return i; }
调用示例:
// 读取u16类型 u16 read_num; EEPROM_get_generic(0x00, &read_num, sizeof(read_num)); // 读取结构体类型 SensorData read_data; EEPROM_get_generic(0x02, &read_data, sizeof(read_data));
3. 进阶:用宏简化调用
每次手动写sizeof略显繁琐,可以用宏封装,让调用体验接近C++模板:
#define EEPROM_PUT(ee, value) EEPROM_put_generic((ee), &(value), sizeof(value)) #define EEPROM_GET(ee, value) EEPROM_get_generic((ee), &(value), sizeof(value))
调用变得非常简洁:
u16 num = 0x1234; EEPROM_PUT(0x00, num); u16 read_num; EEPROM_GET(0x00, read_num); SensorData data = {25.5, 0x01}; EEPROM_PUT(0x02, data); SensorData read_data; EEPROM_GET(0x02, read_data);
注意事项
- 确保传递给函数的指针有效,避免空指针或野指针
- 对于结构体等复杂类型,要注意字节序和内存对齐问题,不同编译器或平台可能有差异,跨平台场景建议手动处理内存布局
Delay_Ms(10)需根据EEPROM型号调整,确保写入完成再执行下一次操作
内容的提问来源于stack exchange,提问作者Mister soccer
相关产品推荐
相关产品推荐

