MISRA:复合赋值运算符
MISRA: Compound Assignment operators
我已经接管了其中有很多复合赋值运算符的代码。
我认为复合运算符不符合 'really' MISRA。
我似乎找不到对它们的任何引用。
我相信我明白发生了什么,实际上应该分开。
UINT16 A |= B; /* Incorrect */
UINT16 A = (UINT16)((UINT32)A | (UINT32)B); /* Correct */
UINT16 A <<= 1u; /* Incorrect */
UINT16 A = (UINT16)((UINT32)A << (UINT32)1u); /* Correct */
那么,我的问题是:
- MISRA 不喜欢复合赋值吗?
- 是否有任何快速修复方法,而不是忽略警告?
谢谢,
Does MISRA frown upon compound assignments?
并非如此。复合赋值的规则类似于简单赋值的规则。 MISRA 泛指赋值运算符,包括所有赋值运算符。
然而,MISRA 不赞成隐式类型提升,请参阅 。除非您了解隐式促销,否则您无法理解这些 MISRA 警告。
Is there any kind of quick fix, instead of ignoring the warning?
如果不理解警告,您将无法真正解决此问题。唯一的快速解决方法是只在所有地方使用 uint32_t
并且从不使用有符号或小整数类型,但这并不总是可行的。如果所有变量都是 uint32_t
.
,您的原始代码将是合规的
一般来说,最新的 MISRA 只允许相同基本类型类别的类型之间的各种转换。无符号整数属于此类,有符号整数属于另一类,依此类推。
在不知道 B
和 sizeof(int)
的类型的情况下,很难判断您的代码到底是如何违反 MISRA 的。这与复合赋值本身无关,除了复合赋值运算符在涉及隐式提升时使用起来有点麻烦。
MISRA 不同意将表达式的值(隐式提升后)分配给同一类别的更窄的基本类型或不同的类别。例如,在简单的英语中,您不应将 uint32_t
操作的结果分配给 uint16_t
变量或将带符号的结果分配给无符号变量。这通常通过在适当的地方进行铸造来解决。
关于你的具体例子,假设 B 是 uint16_t
而 CPU 是 32 位,你会遇到隐式类型提升的问题。
由于A |= B
等同于A | B
,在32位CPU的情况下,通常的算术转换会将操作数提升为int
。所以它是一个带符号的 32 位类型。
假设您有 A << 31u
- 那么这实际上会调用一个未定义的行为错误,该规则试图防止该错误。
MISRA-C 合规性的足够修复:
A = (uint16_t) (A | B); // compliant
A = (uint16_t) ((uint32_t)A << 1u) // compliant
我已经接管了其中有很多复合赋值运算符的代码。 我认为复合运算符不符合 'really' MISRA。 我似乎找不到对它们的任何引用。
我相信我明白发生了什么,实际上应该分开。
UINT16 A |= B; /* Incorrect */
UINT16 A = (UINT16)((UINT32)A | (UINT32)B); /* Correct */
UINT16 A <<= 1u; /* Incorrect */
UINT16 A = (UINT16)((UINT32)A << (UINT32)1u); /* Correct */
那么,我的问题是:
- MISRA 不喜欢复合赋值吗?
- 是否有任何快速修复方法,而不是忽略警告?
谢谢,
Does MISRA frown upon compound assignments?
并非如此。复合赋值的规则类似于简单赋值的规则。 MISRA 泛指赋值运算符,包括所有赋值运算符。
然而,MISRA 不赞成隐式类型提升,请参阅
Is there any kind of quick fix, instead of ignoring the warning?
如果不理解警告,您将无法真正解决此问题。唯一的快速解决方法是只在所有地方使用 uint32_t
并且从不使用有符号或小整数类型,但这并不总是可行的。如果所有变量都是 uint32_t
.
一般来说,最新的 MISRA 只允许相同基本类型类别的类型之间的各种转换。无符号整数属于此类,有符号整数属于另一类,依此类推。
在不知道 B
和 sizeof(int)
的类型的情况下,很难判断您的代码到底是如何违反 MISRA 的。这与复合赋值本身无关,除了复合赋值运算符在涉及隐式提升时使用起来有点麻烦。
MISRA 不同意将表达式的值(隐式提升后)分配给同一类别的更窄的基本类型或不同的类别。例如,在简单的英语中,您不应将 uint32_t
操作的结果分配给 uint16_t
变量或将带符号的结果分配给无符号变量。这通常通过在适当的地方进行铸造来解决。
关于你的具体例子,假设 B 是 uint16_t
而 CPU 是 32 位,你会遇到隐式类型提升的问题。
由于A |= B
等同于A | B
,在32位CPU的情况下,通常的算术转换会将操作数提升为int
。所以它是一个带符号的 32 位类型。
假设您有 A << 31u
- 那么这实际上会调用一个未定义的行为错误,该规则试图防止该错误。
MISRA-C 合规性的足够修复:
A = (uint16_t) (A | B); // compliant
A = (uint16_t) ((uint32_t)A << 1u) // compliant