首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基本数据类型的通用存储

基本数据类型的通用存储
EN

Stack Overflow用户
提问于 2019-05-15 14:56:42
回答 1查看 73关注 0票数 0

存储是内存的一部分:

代码语言:javascript
复制
U08* storage; 

当前的实现只接受U32数据的读/写。

代码语言:javascript
复制
U32 read(void* storage_somewhere) {
    return *(U32*)storage_somewhere;
}

void write(void* storage_somewhere, U32 data_u32) {
    *(U32*)storage_somewhere = data_u32;
}

这是C语言中的标准做法吗?在存储其他数据类型时,是否假定我应该将内存存储到U32中?

既然我需要:

  • 读/写值为1/2/4字节,有符号/无符号/浮动
  • 可移植代码(需要在某些嵌入式系统上运行)

我的理解是,实现如下内容:

代码语言:javascript
复制
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的特定指针转换:

代码语言:javascript
复制
switch(data_type)
...
   case tF32:
       *(F32*)storage_somewhere = val_f32
...

会导致行为不明。

推荐的方法是什么?我认为应该使用memcpy,但这意味着我可以使用保留现有的功能。

EN

回答 1

Stack Overflow用户

发布于 2019-05-15 15:42:01

这是C语言中的标准做法吗?在存储其他数据类型时,是否假定我应该将内存存储到U32中?

这取决于你所说的“这个”是什么意思。在类型void *和其他对象指针类型之间来回转换对象指针是比较常见的,它具有合理的用途(有时也不合理)。另一方面,维护一个平面内存池是不典型的,您可以从内存池中写入和读取不同类型的值。

但是,如果您想要作为一个基本元素的平面池,那么数组的联合可能是一个更好的选择:

代码语言:javascript
复制
#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;

然后,您可以通过表达式直接访问元素,而无需调用函数,例如

代码语言:javascript
复制
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位单元,那么您就有几个基于联合的其他基于联合的备选方案,它们都是基于单个单元的联合,如下所示:

代码语言:javascript
复制
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
};
  • 如果可以确保这样的联合没有填充,则可以将其用作存储和数据交换的基本类型: 联合本原素数= /* . */;uint8_t a_byte = prim.as_uchar;int16_t a_short = prim.as_sshort;float f= prim.as_float;
  • 如果不能假设或确保这样的联合具有正确的存储大小,那么使用它来存储和恢复数据可能比使用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的情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56152316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档