存储是内存的一部分:
U08* storage; 当前的实现只接受U32数据的读/写。
U32 read(void* storage_somewhere) {
return *(U32*)storage_somewhere;
}
void write(void* storage_somewhere, U32 data_u32) {
*(U32*)storage_somewhere = data_u32;
}这是C语言中的标准做法吗?在存储其他数据类型时,是否假定我应该将内存存储到U32中?
既然我需要:
我的理解是,实现如下内容:
void read(void* storage_somewhere, void* data_ptr, DATA_TYPE data_type)
void write(void* storage_somewhere,void* data_ptr, DATA_TYPE data_type)使用基于data_type的特定指针转换:
switch(data_type)
...
case tF32:
*(F32*)storage_somewhere = val_f32
...会导致行为不明。
推荐的方法是什么?我认为应该使用memcpy,但这意味着我可以使用保留现有的功能。
发布于 2019-05-15 15:42:01
这是C语言中的标准做法吗?在存储其他数据类型时,是否假定我应该将内存存储到U32中?
这取决于你所说的“这个”是什么意思。在类型void *和其他对象指针类型之间来回转换对象指针是比较常见的,它具有合理的用途(有时也不合理)。另一方面,维护一个平面内存池是不典型的,您可以从内存池中写入和读取不同类型的值。
但是,如果您想要作为一个基本元素的平面池,那么数组的联合可能是一个更好的选择:
#define WORD_COUNT 1024
union {
int8_t as_schars[WORD_COUNT * 4];
uint8_t as_uchars[WORD_COUNT * 4];
int16_t as_sshorts[WORD_COUNT * 2];
uint16_t as_ushorts[WORD_COUNT * 2];
int32_t as_sints[WORD_COUNT];
uint32_t as_uints[WORD_COUNT];
float as_floats[WORD_COUNT]; // assumes 32-bit floats
} primitives;然后,您可以通过表达式直接访问元素,而无需调用函数,例如
uint8_t a_byte = primitives.as_uchars[42];
int16_t a_short = primitives.as_sshorts[222];
float f = primitives.as_floats[665];
primitives.as_uints[1] = 12;然后,您也不会因为来回转换指针和取消引用结果而导致未定义的行为。
或者,如果您的存储被划分为32位单元,那么您就有几个基于联合的其他基于联合的备选方案,它们都是基于单个单元的联合,如下所示:
union primitive {
int8_t as_schar;
uint8_t as_uchar;
int16_t as_sshort;
uint16_t as_ushort;
int32_t as_sint;
uint32_t as_uint;
float as_float; // assumes 32-bit floats
};memcpy更好:
int16_t read_s16(uint32_t *storage_somewhere) { data (( *storage_somewhere ){ .as_uint = *storage_somewhere }).as_sshort;} write_float(uint32_t *storage_somewhere,浮点数据){*storage_somewhere= ((union原语){ .as_float =data}).as_uint};这些替代方案使编译器尽可能清楚您在做什么,而且它更有可能生成最优代码,而不是针对memcpy的情况。
https://stackoverflow.com/questions/56152316
复制相似问题