2

有问题:

为什么在 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 有什么区别?

我意识到匿名 enum命名 enum之间存在细微差别。但是没有什么能说明规则检查员抱怨另一种形式的原因是什么。

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

4

4 回答 4

3

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

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

于 2015-08-10T22:45:28.380 回答
3

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

让我们解开困惑。

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“枚举的基本类型”通过其他示例很好地放大了这一点。

于 2015-08-11T04:25:46.540 回答
1

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

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

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

于 2015-08-12T10:55:49.843 回答
-1

对枚举进行类型定义(几乎)总是一个坏主意。

最好这样写:

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;

}
于 2015-08-10T20:08:19.357 回答