繁体   English   中英

为什么匿名枚举不能通过MISRA C 2012规则10.3,而命名枚举却不能?

[英]Why does an anonymous enum fails MISRA C 2012 rule 10.3 and a named enum doesn't?

问题:

在C中将其分配给相同的枚举变量类型时,为什么必须强制转换枚举元素?

我的MISRA C 2012规则10.3未能通过该代码出现问题:

表达式的值不应分配给本质类型较窄或本质类型类别不同的​​对象

代码是这样的:

typedef enum
{
   FLS_PROG_SUCCESS,
   FLS_PROG_FAIL,
   FLS_ERASE_SUCCESS2U,
   FLS_ERASE_FAIL,
   FLS_READ_SUCCESS,
   FLS_READ_FAIL,
   FLS_FORMAT_SUCCESS,
   FLS_FORMAT_FAIL
}FLS_JobResult_t;

void Foo(void)
{
   FLS_JobResult_t ProgramStatus;

   /* Then I try to initialize the variable value */
   ProgramStatus = FLS_PROG_SUCCESS;

   ...
}

我接受了一个暗示该工具可能存在缺陷的答案。 我仍然相信,但是鬼混地试图修复,我在typedef枚举声明中添加了一个名称 ,现在是:

typedef enum FLS_JobResult_tag
{
   FLS_PROG_SUCCESS,
   FLS_PROG_FAIL,
   FLS_ERASE_SUCCESS2U,
   FLS_ERASE_FAIL,
   FLS_READ_SUCCESS,
   FLS_READ_FAIL,
   FLS_FORMAT_SUCCESS,
   FLS_FORMAT_FAIL
}FLS_JobResult_t;

据我所知,两者是完全相同的。 但是,然后, 惊喜! 错误消失了! 规则检查器不再将其标记为错误!

然后做一些研究,发现了两个问题:

C中这两种typedef样式之间有什么区别?

这两个枚举声明-C有什么区别?

我意识到匿名枚举命名枚举之间存在细微的差异。 但是,没有什么能清楚说明规则检查器抱怨另一种形式的原因是什么。

所以问题是: 与可能会违反MISRA c 2012规则10.3的匿名枚举和命名枚举有什么区别?

lside (type is anonymous enumeration) = rside (type is anonymous enumeration)左右不知道它是相同的匿名枚举-因此存在潜在的问题。

使用lside (type is named enumeration) = rside (type is _same_ named enumeration) -一切正常,可以使用相同的枚举。

这两个示例都是兼容的,并且都是出于相同的原因:它们没有分配其他必需类型的对象。

让我们清除混乱。

C为开发人员/编译人员在其类型系统中赋予了很大的自由度,但它也可能导致意想不到的结果,并可能导致价值,符号或准确性的损失。 MISRA-C:2012通过其基本类型模型帮助强制执行更安全的键入,该模型为其规则定义提供了合理的基础,从而可以控制类型转换的使用并提高对实现特定行为的意识(10.x规则)。

基本类型模型替代了MISRA-C:2004标准的“基础类型”模型(由于一种原因,这引起了很多程序员对强制执行不必要的强制转换的悲伤)。

我怀疑您的工具很困惑,和/或部分卡在了旧型号上。

与枚举有关的基本类型规则识别两种不同的编程用途:

  1. 旨在与具有不同枚举类型的对象不同的枚举类型的对象。
  2. 枚举是保存一组整数常量的常用方法。

C标准没有提供区分这些用途的方法。 因此,MISRA-C:2012 添加了以下不同的基本枚举类型 (同时不影响C行为):

  1. 命名枚举类型 -在此定义的枚举由标签或typedef标识,或用于任何对象,函数或类型的定义; 如果需要枚举常量的整数值,则必须使用强制类型转换。
  2. 匿名枚举类型 -任何对象,函数或类型的定义中都没有使用的枚举。 通常,这将用于定义一组常量,这些常量可以关联也可以不关联,但避免了强制转换。

匿名枚举类型的示例:

enum {D = 10, E = 20, F = 30};

您的两个示例都被命名为枚举类型 (它们是兼容的,因为它们是相同的基本类型)。 其他示例是:

enum JOHN {A, B, C};
enum PAUL {E, F, G} PAUL;

因此,实际违反10.3的示例为:

enum PAUL bar = B;

参考:MISRA-C:2012附录D.5“枚举的基本类型”通过其他示例很好地放大了这一点。

真正的“错误”实际上在C标准(6.7.2.2)中。 C保证枚举常量的类型为int ,但是枚举变量可以是许多不同的类型,例如char

关于用于枚举常量和枚举变量的基本类型,在MISRA-C:2012附录D.6中进行了描述。 您代码中的枚举常量被认为与命名枚举类型具有相同的基本类型

因此该工具不正确,不应发出诊断信息。

(几乎)定义枚举始终是个坏主意。

最好编写如下:

enum FLS_JobResult_t
{
   FLS_PROG_SUCCESS,
   FLS_PROG_FAIL,
   FLS_ERASE_SUCCESS2U,
   FLS_ERASE_FAIL,
   FLS_READ_SUCCESS,
   FLS_READ_FAIL,
   FLS_FORMAT_SUCCESS,
   FLS_FORMAT_FAIL
};

void Foo(void)
{
   enum FLS_JobResult_t ProgramStatus;

   /* Then I try to initialize the variable value */
   ProgramStatus = FLS_PROG_SUCCESS;

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM