3

我正在为标志使用枚举器值:

typedef enum
{
    a = 0x00,
    b = 0x01u, // the u has no influence, as expected
    c = 0x02u, // the u has no influence, as expected
...
} enum_name;

volatile unsigned char* reg = SomeAddress;
*reg |= b;

根据 MISRA-C:2004 位操作不得使用有符号类型进行。不幸的是,我的编译器 IAR 使用有符号int(或 short 或 char)作为枚举的基础类型,我能找到的唯一选项与大小有关,而不是有符号性(“--enum-is-int”)。

4

2 回答 2

2

根据IAR C/C++ Development Guide for ARM第 169 和 211 页,enum如果启用 IAR 语言扩展(-e命令行选项或Project > Options > C/C++ Compiler > Language > ,则可以定义 s 的类型允许在 IDE 中进行IAR 扩展)。

特别是,您应该定义一个额外的“哨兵”值,以确保编译器选择正确的类型。它更喜欢有符号类型,并使用可能的最小整数类型,因此标记应该是对应的无符号整数类型可以描述的最大正整数。例如,

typedef enum {
    /* ... */
    enum_u8_sentinel = 255U
} enum_u8;

typedef enum {
    /* ... */
    enum_u16_sentinel = 65535U
} enum_u16;

typedef enum {
    /* ... */
    enum_u32_sentinel = 4294967295UL
} enum_u32;
于 2015-08-04T07:22:22.430 回答
2

底层类型是否有符号无符号无关紧要,前提是您只对枚举使用正值,因为正值应该与有符号或无符号类型具有相同的表示形式。标准在 6.2.6.2 表示类型/整数类型§5:符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值。

因此,如果您愿意,您可以安全地对未签名的演员进行演员表。无论如何,如果基础类型是 char(或者是 unsigned char),则可以在任何计算之前(静默)将其提升为 int。

恕我直言,MISRA-C:2004 说 bitwize 操作不应使用有符号类型完成,因为标准明确表示负数的表示是实现定义的:

对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;应该有一个符号位...如果符号位为1,则该值应通过以下方式之一进行修改:

  • 符号位为 0 的对应值取反(符号和幅度);
  • 符号位的值为 -(2N)(二进制补码);
  • 符号位的值为 -(2N - 1)(反码)。

  • 哪些适用是实现定义的(强调我的)

TL/DR:如果你没有警告(你不应该|按位或),你可以安全地使用 no cast。如果您将正值转换为无符号类型,则表示不变,因此如果您(或您的公司规则)选择遵循 MISRA-C,您也可以进行转换,因此您也可以安全地转换为无符号类型

于 2015-08-03T06:08:26.703 回答