为什么匿名枚举不符合MISRA C 2012规则10.3,而命名枚举不';T

为什么匿名枚举不符合MISRA C 2012规则10.3,而命名枚举不';T,c,enums,misra,error-checking,C,Enums,Misra,Error Checking,有关问题: 我因未通过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

有关问题:

我因未通过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 enum声明中加了一个名称,现在是:

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;
据我所知,两者完全相同。但是,惊喜错误消失了!规则检查器不再将其标记为错误

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

我意识到,匿名枚举命名枚举之间存在细微差别。但是,没有任何东西能够明确规则检查者抱怨一种形式的另一种形式的原因

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

键入枚举(几乎)总是一个坏主意

最好是这样写:

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;

}
对于
lside(类型为匿名枚举)=rside(类型为匿名枚举)
左右两侧不知道它是同一个匿名枚举,因此存在潜在问题


使用
lside(类型命名枚举)=rside(类型相同命名枚举)
-一切正常,已知使用了相同的枚举。

两个示例都是兼容的,并且两个示例的原因相同:它们都没有指定不同基本类型的对象

让我们把困惑弄清楚

C在其类型系统中为开发人员/编译器提供了很多自由,但它也可能导致意外的结果,并可能导致值、符号或精度的损失。MISRA-C:2012通过其基本类型模型帮助实施更安全的类型,该模型为其规则定义提供了合理的基础,以控制类型转换的使用并提高对特定于实现的行为(10.x规则)的认识

基本类型模型取代了MISRA-C:2004标准的“底层类型”模型(由于一个原因,这导致了许多程序员执行不必要的强制转换)

我怀疑您的工具有误,和/或部分与旧型号卡住

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

  • 枚举类型的对象,旨在与具有 不同的枚举类型
  • 枚举是保存一组整数常量的常用方法
  • C标准没有给出区分这些用途的方法。因此,MISRA-C:2012增加了以下不同的基本枚举类型(但不影响C行为):

  • 命名枚举类型-此中定义的枚举为 由标记或typedef标识,或用于 任何对象、功能或类型;如果整数 枚举常量的值是必需的
  • 匿名枚举类型-在 任何对象、函数或类型的定义。这通常是 用于定义一组可能相关也可能不相关的常数, 但是避免了铸造的需要
  • 匿名枚举类型的一个示例:

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

    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。代码中的枚举常量被视为与命名枚举类型相同的基本类型


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

    这不应适用于ISO定义的标准C。它应在指定的标准中是特定的。.查找“基本类型”的MISRA定义。它与C中表达式的实际类型不同。只是一个观察:调试器(至少我使用过一些调试器)命名结构和未命名结构也有同样的问题。在内部,对象的类型似乎是由结构标记或枚举标记确定的,而typedef只是编译器使用的别名,而不是调试器或规则检查器使用的别名。@user3386109:我如何确定是否是这种情况?您能解释为什么不使用typede吗f它?它是否适用于
    struct
    s?你能详细说明一下吗?为什么它不好?typedef是结构、联合还是原语呢?这很好,但公司的一个编码规则是,所有结构和枚举都声明为typedef,然后用这些typedef创建变量来使用它们。@hustmrr:我同意,但有一个由许多人组成的团队,既有经验又不太多,这有助于防止人们做奇怪的事情,使代码看起来有点“标准化”,并有助于避免一些错误。这在某种程度上是好的。我不会(暂时)否决投票,但我很想知道你的理由……很高兴与你聊天()
    enum PAUL bar = B;