我正试图找到一种方法来使枚举"无符号".
enum{
x1 = 0,
x2,
x3
};
uint8_t = x2; /* <--- PC-LINT MISRA-C 2004 will complain about mixing signed and unsigned here */
Run Code Online (Sandbox Code Playgroud)
当然,我可以添加一个类型转换来摆脱错误,这是耗时且容易出错的.
uint8_t = (uint8_t)x2; /* This works, but is a lot of extra work over the course of 1000s of lines of code*/
Run Code Online (Sandbox Code Playgroud)
那么,有没有办法让MISRA-C 2004想要的特定枚举无符号?
Car*_*rum 11
没有标准的C方式来控制所选择的类型enum.您有时可以以特定于实现的方式执行此操作,例如通过向枚举添加一个强制类型为unsigned的值:
enum {
x1,
x2,
x3,
giant_one_for_forcing_unsigned = 0x80000000;
};
Run Code Online (Sandbox Code Playgroud)
但这也不是标准C(因为提供的值不适合int).不幸的是,你几乎没有运气.这是标准中的相关位:
6.7.2.2枚举说明者,第4段
每个枚举类型应与
char有符号整数类型或无符号整数类型兼容.类型的选择是实现定义的,但应能够表示枚举的所有成员的值.枚举类型在}终止枚举器声明列表之后立即完成,并在此后完成.
你可能最好#define不要使用而不是enum制作你的常量:
#define x1 0U
#define x2 1U
#define x3 2U
uint8_t x = x2;
Run Code Online (Sandbox Code Playgroud)
这里有几个问题,转换错误的可能性很小,MISRA试图让你避免:
枚举常量,即x1示例中的等等,保证为类型int(1).但枚举变量和变量类型枚举不能保证属于同一类型(2),如果你运气不好,它被定义为一个小整数类型,因此受整数提升规则的约束.
MISRA禁止将大整数类型的隐式转换为较小的整数类型,主要是为了避免无意中截断值,而且还避开各种隐式提升规则.
您的具体MISRA合规性错误实际上来自上述后一个问题,违反了规则10.3(3).
您可以通过向"基础类型"(预期类型)添加显式强制转换来解决此问题,在本例中为强制转换为uint8_t.或者你可以通过永远不使用枚举来解决它,用#defines替换它们.这可能听起来很激进,但请记住,C没有任何类型安全性,因此除了可读性之外,使用枚举没有明显的好处.
以这种方式替换枚举有点常见:
#define FALSE 0
#define TRUE 1
typedef uint8_t BOOL;
Run Code Online (Sandbox Code Playgroud)
(虽然在这个例子的目的主要是为了使BOOL型便携,具有保证为8位,从来没有16位,如可能的情况下发生的,这是一个枚举.)
参考文献:
(1)C11 6.2.7.7/2:
"定义枚举常量值的表达式应该是一个整数常量表达式,其值可以表示为int."
(2)C11 6.2.7.7/4:
"每个枚举类型应与char,有符号整数类型或无符号整数类型兼容.类型的选择是实现定义的,但应能够表示枚举的所有成员的值."
(3)MISRA-c:2004年规则10.3:
"整数类型的复杂表达式的值只能转换为与表达式的基础类型相比更窄且具有相同符号的类型."
在C90中,不仅没有办法指定enum对无符号类型进行处理,而是在C90中:
声明为枚举常量的标识符的类型为int
这也适用于C99(6.4.4.3).如果您想要一个无符号类型,那么您正在查看语言扩展.
该枚举类型可能会比其他的东西int,但常数本身必须有int类型.