c - 静态断言 enum 是某种基础类型

标签 c enums c99 static-assert misra

MISRA 10.1 禁止对枚举类型的对象执行算术。

An operand of essentially enum type should not be used in an arithmetic operation because an enum object uses an implementation-defined integer type. An operation involving an enum object may therefore yield a result with an unexpected type. Note that an enumeration constant from an anonymous enum has essentially signed type.

他们还规定,就本规则而言,++-- 一元运算符被视为二进制加法和减法。

如果我在循环控制结构中使用整数,我仍然需要稍后将它们转换回枚举,这将违反规则 10.5

The value of an expression should not be cast to an inappropriate essential type

有没有一种方法可以使用静态断言来保证有关底层枚举类型的一些假设?该代码将来可能会在另一个架构上重用。在这种情况下,我希望偏离 10.5,并且确信如果违反了有关底层枚举类型的某些假设,代码将引发编译时错误。

人为的示例:

enum {thing1, thing2, ... , thing_max } thing_index_t
...
for(int thing_index = 0; thing_index < (int) thing_max; ++thing_index)
{
    init_something((thing_index_t) thing_index);
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~
    // cannot cast a signed value to an enum type
    // [MISRA 2012 Rule 10.5, advisory]
}

如果我静态断言 sizeof(thing_index_t == int);thing1 == 0u 对吗?

Int 总是足够大,可以容纳我的整个值范围,而无需提升 FWIW。

最佳答案

规则 10.5 总体上是合理的,但从 enum 到有符号/无符号的受控转换并不危险。 MISRA 担心您可能有一个类似于 enum {thing1=123, thing2=456, ... 的枚举。但是,如果您知道枚举器常量从 0 到 max,则转入/转出整数基本上是安全的。

您不需要咨询规则的正式偏差。我宁愿留下评论,例如

/*  Violates MISRA 10.5 but iterating from thing1 to thing_num is safe. 
    Integer type is used since arithmetic on enums is forbidden by 10.1. */

(或者使用您现有的任何流程来处理咨询规则。)


对于静态断言,sizeof(thing_index_t == int) 没有证明什么,因为允许的枚举常量值才是重要的。并且 thing1 == 0u 由 C 标准保证,因此您无需断言。

确保枚举完整性的静态断言应该看起来像

#define THING_VALUES   \
  thing1,              \
  thing2,              \
  thing_num            \

typedef enum { thing1=123, thing2=456, thing_num } thing_index_t;
const size_t expected_size = sizeof((thing_index_t[]){ THING_VALUES }) / sizeof(thing_index_t);

_Static_assert( thing_num+1 == expected_size );

其中复合文字 (thing_index_t[]){ THING_VALUES }) 获取与列表中枚举常量的数量相对应的大小。 expected_size 是项目数量。这断言不存在特殊的初始化程序,例如 thing1=123

唯一的漏洞是一些奇怪的东西,比如 thing1=123, thing2=1,这是无法捕获的。为了防止这种情况,您需要进一步使用宏,使用 X 宏等来实现整个事情。

关于c - 静态断言 enum 是某种基础类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54316282/

相关文章:

附加字符后无法释放分配的字符串内存

c# - 将两个 if 合二为一

C 最小值/最大值函数

c - 警告 : implicit declaration of function 'Min' is invalid in C99 [-Wimplicit-function-declaration]

windows - C99 代码在 Linux 上编译,在 Windows 上语法错误

c - 如何确保静态库和应用程序编译相同?

c - 向文本文件写入 1024 字节时,文本文件变成二进制文件 (linux)

ios - Swift:从另一个 viewController 类访问枚举

java - Java 中枚举列表的结尾

c - 使用序列化二叉搜索树对海量数据进行排序