MISRA 违规 12.9 一元减号的操作数是无符号的

MISRA Violation 12.9 Operand of unary minus is unsigned

我目前正在处理一些 MISRA 问题,因此试图了解 C 中的整数转换规则。

我违反了 MISRA-C 2004 规则 12.9 一元减号运算符不得应用于基础类型为无符号的表达式

在代码行

signed long int test = -1;

我知道没有负整数常量“-1”,而是应用于整数常量“1”的一元减号(如 https://en.cppreference.com/w/c/language/integer_constant 中所述)。

然而整数常量“1”是列表中的第一个类型 int, long int, unsigned long int(C99 前)long long int(C99 起)

我正在编译 Keil(ARM 32 位)和 --c99 标志集,而 MISRA-C 2004 似乎是基于 C90 标准。

所以我的 SCA 工具似乎假设“1”常量的类型为 unsigned long int(C99 之前),但我不明白为什么会这样'适合普通 int 并因此被签名。

要满足SCA工具,就得写代码

signed long int test = -1L;

signed long int test = -((signed long int) 1);

这是正确的行为还是我遗漏了什么?

The integer constant "1" however is of the first type in the list int, long int, unsigned long int...

正确。像 1 这样的整数常量是 int 类型,就 MISRA-C 而言,基础类型也是 int。定义是 (MISRA-C:2004 6.10.4)

The term "underlying type" is defined as describing the type that would be obtained from evaluating an expression if it were not for the effects of integral promotion.

signed long int test = -1; 符合 MISRA-C:2004(和 MISRA-C:2012)。

  • 表达式 -1 本身不包含隐式促销。积分促销不适用。
  • 因此 -1 具有带符号的基础类型 int 并且在分配时,它被隐式转换为具有相同符号的更广泛的整数类型,这很好。
  • 目的是创建一个带符号的变量,因此关于 u 后缀的规则不适用。
  • 此外,禁止从所谓的 "complex expression" 隐式转换为不同类型的规则 10.1 也不适用,因为 -1 是常量表达式,而不是复杂表达式(参见 MISRA -C:2004 6.10.5).

所以这是另一个工具错误。该工具似乎选择了错误的表达式基础类型,这将是一个严重的错误。

signed long int test = -1L; 不是合规所必需的,尽管它也是合规代码。