首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将结构转换为uint8_t (错误:请求转换为非标量类型)

如何将结构转换为uint8_t (错误:请求转换为非标量类型)
EN

Stack Overflow用户
提问于 2020-06-15 07:29:50
回答 2查看 808关注 0票数 2

我需要在EEPROM中存储8个继电器的状态。我不想为移动而烦恼,我喜欢使用位字段。所以我想这样定义它们:

代码语言:javascript
复制
typedef struct{
    uint8_t RELAY0_STATE:1;
    uint8_t RELAY1_STATE:1;
    uint8_t RELAY2_STATE:1;
    uint8_t RELAY3_STATE:1;
    uint8_t RELAY4_STATE:1;
    uint8_t RELAY5_STATE:1;
    uint8_t RELAY6_STATE:1;
    uint8_t RELAY7_STATE:1;
}relay_nvm_t;

relay_nvm_t   relay_nvm;

在我的主要代码流中,我使用relay_nvm变量设置每个中继的状态。示例

代码语言:javascript
复制
...
if(something)
{
    relay_nvm.RELAY0_STATE = 1;
    relay_nvm.RELAY1_STATE = 0;
    relay_nvm.RELAY2_STATE = 1;
    relay_nvm.RELAY3_STATE = 0;
    relay_nvm.RELAY4_STATE = 1;
    relay_nvm.RELAY5_STATE = 1;
    relay_nvm.RELAY6_STATE = 0;
    relay_nvm.RELAY7_STATE = 1;
}

最后,当我需要对EEPROM进行读写时,我只是将relay_nvm转换为uint8_t,以便将一个字节读/写到EEPROM。但我得到了error: conversion to non-scalar type requested错误。以下是我的职责。

代码语言:javascript
复制
static void NVM_Relay_Read(void)
{
    relay_nvm = (relay_nvm_t)NVM_ReadEepromByte(NVM_RELAY_INDEX);
}

static void NVM_Relay_Write(relay_nvm_t rs)
{
    NVM_WriteEepromByte(NVM_RELAY_INDEX, (uint8_t)rs);
}

我们有办法克服这个错误吗?我以为我可以用打字机来做。位字段的使用使我的工作非常容易,代码更容易理解。

我知道在这种情况下,由于填充的原因,位字段可能不安全,但我认为我可以使用POP-PUSH (它值得吗?)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-15 07:42:18

我看到了更多的方法来处理这件事:

  1. 使用联合。
  2. 使用指针类型转换:
  3. uint8_t:

代码语言:javascript
复制
    uint8_t relay_nvm;
    #define RELAY0_MASK 1
    #define RELAY1_MASK 2
    #define RELAY2_MASK 4
    ...
    #define RELAY7_MASK 128

    // set exact relays state:
    relay_nvm = RELAY0_MASK | RELAY2_MASK | RELAY4_MASK | ... ;

    // set single relay (others left unchanged):
    relay_nvm |= RELAY2_MASK;

    // clear single relay (others left unchanged):
    relay_nvm &= ~RELAY2_MASK;

    // check current state of a relay:
    if (relay_nvm & RELAY2_MASK) { ... }
票数 3
EN

Stack Overflow用户

发布于 2020-06-15 09:30:31

,我不想麻烦移动,我喜欢使用位字段。

如果使用按位运算符是一个“麻烦”,那么你可能不应该写嵌入式系统代码,直到你掌握了它们的窍门.对于编写非标准的、不可移植的代码来说,这是一个非常糟糕的理由。

与按位版本不同的是,位字段存在大量问题:未定义的位顺序、无依赖项、未指定的符号性、对齐和填充打嗝等等。您已经在用uint8_t位字段编写特定于平台的代码,因为C标准没有涵盖这些代码。

如果坚持使用位字段,则必须阅读特定的编译器文档,说明它们是如何实现的。不要假设有任何关于如何分配事物的保证,因为在这种情况下没有标准化。

您的具体问题是,您不能直接从结构类型(简单地说是“容器类型”)转换为uint8_t和back,原因与不能使用数组进行转换的原因相同。您必须使用指向第一个元素的指针,然后将其转换为uint8_t*和去引用。但这也伴随着一系列与对齐、兼容类型和“严格混叠”相关的问题。

结构和联合在一般情况下并不适合用于内存映射,尤其是在可移植性方面。至少,您必须启用#pragma pack(1)或类似的编译器特定命令的打包。

因此,您应该考虑完全删除位字段,并在原始uint8_t上使用位运算符,因为这样可以解决太多的问题。

顺便提一下,存储在EEPROM中的所有变量都必须是volatile限定的,所有指向它们的指针也必须是限定的。否则,当您启用优化时,程序很有可能会失控。

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

https://stackoverflow.com/questions/62383368

复制
相关文章

相似问题

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