Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在不违反MISRA规则的情况下将位字段变量分配给uint8_t变量?_C_Bit Fields_Misra_Uint8t - Fatal编程技术网

C 如何在不违反MISRA规则的情况下将位字段变量分配给uint8_t变量?

C 如何在不违反MISRA规则的情况下将位字段变量分配给uint8_t变量?,c,bit-fields,misra,uint8t,C,Bit Fields,Misra,Uint8t,我有一个typedef结构命名字符 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 Ch

我有一个
typedef结构
命名字符

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变量(值为
0
1
)分配给其中一个位字段时,我违反了MISRA规则10.6,其中规定:

复合表达式的值不得指定给 基本类型较宽的对象


有没有一种方法可以在不违反MISRA C的情况下将位字段分配给uint8_t?

正是出于这个原因,我发现MISRA C过于复杂。 无论如何,你没有说你想直接分配它。如果是这种情况,您可以采取以下措施:

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
而不是位字段来设置这些值。比如说,

tempChar.u8Value |= (1 << 0);
if(1 == tempChar.a)
{ 
    // Some code
}

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

表达式的结果是一个
int

升级和从
int
unsigned int
的转换虽然在正常情况下完全有效,但足以让非常严格的MISRA投诉

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

tempChar.a = pData[0] >> 5;
在本例中,
5
是一个有符号整数常量。对于无符号常量,应使用
5U

此外,右移操作的结果将是
int
,因此需要键入cast将结果转换回
unsigned int

tempChar.a = (unsigned int) (pData[0] >> 5U);

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

您的位字段是在MS字节还是LS字节中分配8个值位?它是按照经久不衰的规律进行的,还是不按照经久不衰的规律进行的?比特顺序是什么?没人知道。第一步是去掉位字段

第二步是去掉任何
无符号int
并使用
uint16\u t
/
uint32\u t


特别是对于MISRA-C10.6,禁止隐式转换为更广泛类型的规则总是被误导了。MISRA用于该规则的基本原理是防止人们编写类似于
uint32\u t u32=u16a+u16b的代码
并且认为
=
u32
操作数以某种方式神奇地意味着该操作将在32位而不是16位上执行。但在8/16位系统上,它是用16位算法执行的,可能会出现溢出/环绕

现在,在有符号类型上进行位移位总是一个非常糟糕的主意
pData[0]
被隐式提升为
int
,并被签名。MISRA还有其他规则处理这个问题,而不是你引用的规则


不管MISRA如何,您都应该养成习惯,总是在未签名类型上执行移位。“在这种情况下并不危险”是一个令人沮丧的理由。这意味着始终写入
(uint32_t)pData[0]>>5
,并且应在轮班之前而不是之后应用强制转换。这消除了所有与未定义行为左移和可能的算术右移等有关的不确定性。让优化器担心操作数的实际使用大小。

您是如何得到此警告的?如何编译代码?我正在使用一个工具进行静态分析。我必须遵守MISRA C.您是否尝试过
tempChar.a=(uint8_t)(pData[0]>>5)?是的。这没有帮助。请尝试避免升级:
tempChar.a=((未签名)pData[0])>>5哦,更简单。为什么我一开始就想到了工会(使用
~pData[0]>>5
运行相同的代码。然后,
~(uint32\u t)pData[0]>>5
。然后抱怨MISRA…当然,除非您认为将值-1存储在
:1
位字段中是个好主意。