首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在不违反MISRA规则的情况下将位字段变量赋值给uint8_t变量?

如何在不违反MISRA规则的情况下将位字段变量赋值给uint8_t变量?
EN

Stack Overflow用户
提问于 2020-01-27 09:36:27
回答 4查看 1.3K关注 0票数 4

我有一个名为typedef struct的字符。

代码语言:javascript
运行
复制
typedef struct {
    unsigned int a : 1;
    unsigned int b : 1;
    unsigned int c : 1;
    unsigned int d : 1;
    unsigned int o : 1;
    unsigned int p : 1;
    unsigned int q : 1;
    unsigned int x : 1;
} Character;

static Character tempChar;

void writeVar(const uint8_t *pData)
{
    tempChar.a = pData[0] >> 5;
    ...
}

当我试图将一个uin8_t变量(值为01)分配给这些位字段之一时,我违反了MISRA规则10.6,其中规定:

复合表达式的值不应赋值给具有更广泛基本类型的对象。

有没有一种在不违反MISRA的情况下为uint8_t分配位字段的方法?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-01-27 10:09:58

如果需要的话,表达式pData[0] >> 5中的两个操作数将是到int (这将发生在pData[0]中)。

表达式的结果是一个int

晋升和从intunsigned int的转换,虽然在正常情况下是完全有效和罚款的,但足以让非常严格的MISRA抱怨。

简单的解决方案(如注释所示)是使用强制转换将pData[0]显式转换为unsigned int

票数 4
EN

Stack Overflow用户

发布于 2020-01-27 16:06:06

这里的核心问题与MISRA无关,而与试图将值存储在位字段中的特定时隙有关。您无法知道您的位字段布局实际上是如何在内存中结束的,因为这在C标准中没有定义。

您的位字段是在MS字节还是LS字节中分配8个值位?它是按照规定取得的,还是不符合?点位顺序是什么?没人知道。第一步是去掉位字段.

第2步是摆脱任何unsigned int,并使用uint16_t/uint32_t

特别是Misra-C10.6,反对隐式转换到更广泛类型的规则总是被误导的。这条规则使用的基本原理是防止人们编写像uint32_t u32 = u16a + u16b;这样的代码,并认为=u32操作数在某种程度上意味着操作将在32位而不是16位上执行。但在8/16位系统上,它是用16位算术执行的,可能会出现溢出/环绕。

现在,对有符号类型进行位转换总是一个非常糟糕的主意。pData[0]被隐式提升到被签名的int。还有其他米斯拉规则来处理这个问题,而不是你引用的那条。

不管米斯拉如何,你都应该养成一个习惯,在没有符号的类型上执行你的轮班。“在这种情况下这并不危险”是一个黯淡的理由。这意味着始终编写(uint32_t)pData[0] >> 5,转换之前应该应用强制转换,而不是在转换之后。这消除了与未定义的行为、左移位和可能的算术右移位等有关的所有不确定性。让优化器考虑操作数的实际使用大小。

票数 1
EN

Stack Overflow用户

发布于 2020-01-27 10:09:17

因为这个原因,我觉得米斯拉·C太复杂了。不管怎样,你没说你想直接分配它。如果是这样的话,你可以采取以下措施:

代码语言:javascript
运行
复制
typedef union {
    
    struct {
        unsigned int a : 1;
        unsigned int b : 1;
        unsigned int c : 1;
        unsigned int d : 1;
        unsigned int o : 1;
        unsigned int p : 1;
        unsigned int q : 1;
        unsigned int x : 1;
    };
    
    uint8_t u8Value;
    
} Character;

并通过访问tempChar.u8Value而不是位字段来设置这些值。例如,

代码语言:javascript
运行
复制
tempChar.u8Value |= (1 << 0);

tempChar.a设置为1

这仍将保持代码的整洁(可读性)在同样程度上。例如,

代码语言:javascript
运行
复制
if(1 == tempChar.a)
{ 
    // Some code
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59928364

复制
相关文章

相似问题

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