在结构中使用 typedef 枚举并避免类型混合警告
Posted
技术标签:
【中文标题】在结构中使用 typedef 枚举并避免类型混合警告【英文标题】:Working with typedef enums in structs and avoiding type mixing warnings 【发布时间】:2015-01-24 02:56:38 【问题描述】:我正在使用 C99。我的编译器是 IAR Embedded Workbench,但我认为这个问题对其他一些编译器也有效。
我有一个 typedef 枚举,其中包含一些项目,我向该新类型的结构添加了一个元素
typedef enum
foo1,
foo2
foo_t;
typedef struct
foo_t my_foo;
...
bar_t;
现在我想创建一个 bar_t 的实例并将其所有内存初始化为 0。
bar_t bar = 0u ;
这会生成一个警告,提示我将枚举与另一种类型混合。 IAR 特定警告编号为 Pe188。它编译和工作得很好,因为枚举在一天结束时是一个无符号整数。但我想避免一千个烦人的警告。将其中包含枚举类型的结构类型初始化为 0 的干净方法是什么?
为了争论,我们假设 bar_t 有很多成员 - 我只想将它们全部设置为 0。我不想输入这样的内容:
bar_t bar = foo1, 0u, some_symbol,... , 0u;
编辑:额外说明:我遵守 MISRA。因此,如果解决方法将违反 MISRA,它只会为我解决问题。我会被 MISRA 检查器唠叨。
【问题讨论】:
提供一个具有“默认”值的枚举? 好吧,在这种情况下,“默认”值将是 foo1,因为除非我另有说明,否则它将为 0。但即使我说 foo1 = 0,在枚举中我仍然会看到此警告。 您必须执行bar_t bar = foo1 ;
在这种情况下您仍然看到警告吗? (假设您将 foo1 定义为 0)
我要编辑我的 OP - 我还必须遵守 MISRA 规则。这样做可以消除编译器警告,但我的 linting 工具会违反非零初始化。
“枚举是一天结束时的无符号整数” - enum
是普通的 int
,而不是 unsigned int
。
【参考方案1】:
如果你真的,字面意思想要将一个结构的所有内存初始化为 0,那么就是这样写的
memset(&bar, 0, sizeof(bar_t));
这实际上是相当普遍的,而且它甚至会起作用,但从技术上讲,它对于大多数人真正想要的东西是不正确的。对于大多数元素类型,它不能保证做正确的事情,因为 C 做出的保证比许多人对不同类型值的表示以及各种位模式的含义所做的保证要少。
初始化聚合对象(例如结构体)的正确方法,就像将值零分配给每个元素一样是您开始的方法,尽管编写它的规范方法很简单
bar_t bar = 0 ;
(不需要'u'后缀)。该变体极有可能避免编译器警告,尽管我并不期望如此。
Ashalynd 给出了我认为最正确的答案(即
bar_t bar = foo1 ;
)。如果这以某种方式违反了您必须遵守的代码约定,那么也许您可以重新组织您的 struct
以便第一个元素是 enum
类型以外的任何类型。
【讨论】:
重新组织结构,以便首先使用非枚举类型。现在 bar_t bar = 0 ;将在没有任何警告或违反 MISRA 的情况下工作。但是为什么枚举是否是第一个重要呢? 我不想“从字面上”将此内存初始化为 0 :)。我宁愿以规范的方式来做。在这种情况下,我实际上将它用于静态内存,但这个问题仍然适用于动态或 statck)。但是,如果我使用 = 0 初始化静态内存,我的链接器将知道自动将此结构放置在完全初始化为 0 的段中。如果我所有归零的内存都分组,它可以使我的内存映射更清晰,更容易遵循相同的段,还可以在启动时节省一些周期。 这很重要(对您的编译器而言),因为= 0
中的 0
显式初始化了 first 标量成员(为子结构、子联合和递归定义)子数组),其余部分被隐式初始化为0
。 = 0
是一个常见且有用的习语,一个好的 C 编译器不应该抱怨它。
@Kieth 说了什么。这也是为什么当你的enum
是第一个时编译器会抱怨的原因——如果你写foo_t f = 0u
,它会(应该)发出完全相同的警告——以及为什么我说Ashalynd 的bar_t bar = foo1
更正确。许多编译器确实警告将int
s 分配给enum
s,因为分配的值可能不对应于任何声明的枚举常量。
感谢您的解释!我将把它归档,以确保标量成员最终出现在我的数组中的第一个位置一个联合。以上是关于在结构中使用 typedef 枚举并避免类型混合警告的主要内容,如果未能解决你的问题,请参考以下文章
枚举类型 typedef enum....; enum....; 这两个的区别
如何在 Angular 中定义枚举类型以不违反 tslint typedef 规则