【问题标题】:Does MISRA C 2012 say not to use boolMISRA C 2012 是否说不使用 bool
【发布时间】:2015-08-16 22:00:33
【问题描述】:

我正处于一个新项目框架的早期阶段。

我定义了一个返回类型为“bool”的函数

我从 PC-Lint 得到了这个输出

    Including file sockets.h (hdr)
bool sock_close(uint8_t socket_id);
^
"LINT: sockets.h (52, 1) Note 970: Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]"

我继续在另一个标题中定义了这个来关闭 lint:

typedef bool bool_t;

然后我开始想知道为什么我必须这样做以及为什么它会改变任何东西。我转向 MISRA 2012 Dir 4.6。它主要关注原始类型(如 short、int 和 long)的宽度、宽度以及它们的签名方式。

标准没有给出 bool 的任何放大、合理、例外或示例。

bool 在 C99 的 stdbool.h 中明确定义为 _Bool。那么这个标准真的适用 bool 吗?

根据 C99 的第 6.2.5 节,我认为 _Bool 始终是“足以存储值 0 和 1 的最小标准无符号整数类型”。所以我们知道 bool 是无符号的。那么 _Bool 不是固定宽度并且主题以某种方式被提升的事实是否只是问题所在?因为理性似乎与这个概念相矛盾。

遵守本指南并不能保证可移植性,因为 int 类型的大小可能决定表达式是否接受整数提升。

仅仅放置typedef bool bool_t; 会如何改变任何事情——因为我没有做任何事情来表明这样做的宽度或签名? bool_t 的宽度也将取决于平台。有没有更好的方法来重新定义 bool?

除非实现的类型实际上具有该长度,否则不得以特定长度定义类型

所以typedef bool bool8_t; 应该是完全非法的。

Gimpel 对指令 4.6 的解释是错误的还是他们发现了?

【问题讨论】:

  • _Bool 是 C99 中的原生类型,对于 Misra,您不能直接使用原生类型。这通常是为了代码可移植性。有时 int 是(有符号的)32 位,有时是(有符号的)16 位,例如在 8 位平台上。所以你的代码应该 typedef s32 或 s16 来明确说明你的需求
  • MISRA 没有说“不要使用本机类型”。指令 4.6 说“应该使用指示大小和符号的 typedef 来代替基本的数字类型”。我的问题是 _Bool 是否符合基本数字类型的定义。我正在查看 MISRA C 2012 的第 28-30 页,但他们没有明确说明 bool 的任何内容——尽管他们详细讨论了 stdint 中的 typedef。
  • 一个数据点:bool(在<stdbool.h>中定义的是一个扩展为_Bool的宏,而不是一个typedef。bool/_Bool的宽度和符号应该是无关紧要的只要您正确使用它;如果 MISRA 确实建议不要使用它(同时允许您的 typedef),那似乎很愚蠢。
  • @KeithThompson 同意,_Bool 是特殊的,应该优先于 typedef uint8_t bool_t;
  • 听起来好像省略 <stdbool.h> 并添加 typedef _Bool bool; 会起作用。

标签: c language-lawyer c99 misra pc-lint


【解决方案1】:

在 typedef 之外使用修饰符或类型“_Bool”[MISRA 2012 Directive 4.6,advisory]

这是废话,指令 4.6 只关心使用 stdint.h 中的类型,而不是 intshort 等。该指令是关于基本的数字类型bool 与该指令无关,因为它不是数字类型。

由于未知原因,MISRA-C:2012 示例使用了一种称为bool_t 的奇怪类型,这不是标准的。但是 MISRA 绝不会强制这种类型在任何地方使用,特别是它们在指令 4.6 中没有强制使用它,甚至没有提到布尔值。 MISRA 不鼓励在任何地方使用 bool_Bool

Gimpel 对指令 4.6 的解释是否错误

是的,他们的工具给出了不正确的诊断。

此外,您可能必须配置工具(如果可能)以告诉它使用哪种布尔类型。 5.3.2 提到如果不使用_Bool,您可能必须这样做,这意味着所有静态分析器都必须理解_Bool。但是即使bool类型配置正确,dir 4.6也没有关系。

【讨论】:

  • 我在 MISRA C 2012 中查看了对 bool_t 的引用,它们似乎经常被用作一些不一定显式 _Bool 的有效 bool 值的示例。我想这与 C90 相关,也许 MISRA 试图让他们的示例同时适用于 C99 和 C90,因为它涵盖了两者。
  • Gimpel 的支持人员也同意这是误报。所以我打算在我的项目的 lnt 文件中使用 -esym(970,_Bool) 来取消关于 bool 的注释 970。
  • 同意 - bool 可以使用。
【解决方案2】:

布尔类型的一个潜在问题是 C99 之前的许多代码使用单字节类型来保存真/假值,其中相当一部分可能使用了名称“bool”。尝试将 256 的任何倍数存储到大多数此类类型中将被视为存储零,而将 256 的非零倍数存储到 c99“bool”将产生 1。如果使用 C99“bool”的一段代码是移植到使用 typedef 字节的一段代码中,生成的代码很容易发生故障(在存储 0 或 1 以外的值时,为 typedef 字节编写的代码不太可能依赖于任何特定行为)。

【讨论】:

  • 一旦我意识到它就会出现明显的问题......但之前没有。有趣的是,它不会通过 typedefing 字节来修复(但我猜 lint 会很高兴)。
  • @Peter-ReinstateMonica:我不喜欢在 C99 中定义 bool 的方式。如果 C99 指定用任何奇数写入的布尔值将读取未指定的奇数,则写入为零的布尔值将读取为零,读取任何其他布尔值将产生未指定的值(偶数、奇数或零),这将允许实现更有效地处理使用bool 的代码。如果例如一个函数在int 中返回一个标志,代码需要将其存储到bool,如果非零偶数需要被视为1,则让程序员编写!!function(whatever),但让程序员...
  • ...如果不需要!!,则省略,在许多情况下,与要求编译器始终表现得好像存在!! 相比,这将允许更有效的代码生成.
猜你喜欢
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多