【问题标题】:MISRA 19.4 clarificationMISRA 19.4 说明
【发布时间】:2018-07-17 12:19:24
【问题描述】:

我想在我的文件中使用以下宏

#define DO_WAKEUP_SYNCHRONISIEREN proc.id = process_WAKEUP;proc.priority.level = PRIO_AKTIV_1;proc.priority.param=0u;(void)prio_mapF_put_in_matrix(proc)

我知道这违反了 MISRA-C:2004 规则 19.4 - 但我需要使用它来解决违规问题。

有什么方法可以使用 MACRO 并解决 MISRA-C 违规问题?

MISRA-C:2004 规则 19.4 是

C 宏只能扩展为花括号初始化器、常量、 字符串文字、带括号的表达式、类型限定符、 存储类说明符,或 do-while-zero 构造。

【问题讨论】:

  • 最好将宏代码包装在do {} while(0) 中,以便在条件下将其视为唯一的“指令”。
  • @Jean-FrançoisFabre 我收到以下消息“违反 MISRA 2004 所需规则 19.4,不允许定义宏 'DO_WAKEUP_SYNCHRONISIEREN'”

标签: c misra


【解决方案1】:

看起来规则是:

#define B A

以上不是此规则下允许的宏定义形式,因为 A 不是常量、大括号初始化器、带括号的表达式、类型限定符、存储类说明符或 do-while-zero 构造

#define B (A)

以上是允许的。替换列表是带括号的表达式。

对此的扩展将是(即使没有 MISRA 约束我也会这样做,但我只是注意到规则指出:“做零时构造”,恕我直言,乍一看并不明显“做- while-zero 构造”意味着当你不知道这一点时......):

#define DO_WAKEUP_SYNCHRONISIEREN do {proc.id = process_WAKEUP;proc.priority.level = PRIO_AKTIV_1;proc.priority.param=0u;(void)prio_mapF_put_in_matrix(proc);} while(0)

所以指令块不能被这样的结构“部分调用”:

if (flag) DO_WAKEUP_SYNCHRONISIEREN;

这会让任何试图理解错误的人头疼。

同时它强制添加一个;,而不是一个简单的{} 块。所以这个宏看起来很像一个函数调用(也可以阅读Why use do { } while (0) in macro definition?)。

【讨论】:

  • 顺便说一句(也许很有趣),MISRA C:2012 放宽了这个要求——尽管我个人仍然建议使用大括号或圆括号来绑定宏,除非另有要求
  • 也许他们这样做了,所以可以定义 case x: do_##x() 东西......不知道。这条规则对我来说是个好主意,而且每条规则都有例外。
  • do while(0) 已从 MISRA-C 版本 2012 中删除。早期的 MISRA-C 建议使用这种做法,但由于 do while(0) 允许您编写控制/循环语句而受到批评不是复合语句,这反过来又是不同的 MISRA 规则所要求的。 do while(0) 技巧的全部目的是允许诸如if(x) macro(); else 之类的代码。但 MISRA-C 兼容代码必须是 if(x) { macro(); } else。所以 do-while(0) 技巧是有害的,因为它会阻止编译器检测 MISRA-C 违规。
  • 感谢您的澄清。 do while(0) 技巧的全部目的(在 SO 上详细介绍)是允许阻止并最终仍然强制使用 ;,而 if(x) { macro(); } else 无法确保这一点。正如您所说,没有完美的世界,有时规则会像您提到的那样相互矛盾。当您知道自己在做什么时,就会有一些理由违反规则。
猜你喜欢
  • 2019-04-02
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 2011-01-04
  • 2015-04-03
  • 2013-10-19
  • 2013-08-28
相关资源
最近更新 更多