【问题标题】:Prevent "enumerated type mixed with another type" warnings for boolean values in Keil uVision防止 Keil uVision 中布尔值出现“枚举类型与其他类型混合”警告
【发布时间】:2018-12-26 05:54:33
【问题描述】:

我正在将我在 CodeWarrior v5.2 中开发的应用程序迁移到使用 ARM C 编译器 v5.06 的 Keil uVision v5.25。

在我的代码中,我使用bool 来表示布尔值,它在我的项目的types.h 文件中定义为:

typedef enum _bool 
{ 
  false = 0, 
  true = 1 
} bool;

当我尝试编译我的代码时,编译器会生成有关我将比较结果隐式分配给这种类型的变量的行的警告:

src\c\drivers\motor.c(168): warning:  #188-D: enumerated type mixed with another type
    const bool motorStopped = timeSinceLastEvent > maxPulseWidth;
src\c\drivers\motor.c(169): warning:  #188-D: enumerated type mixed with another type
    const bool motorStalled = motorStopped && isMotorDriven();

我了解为什么会生成这些警告。我知道我可以通过显式转换为 bool 来抑制这些警告,例如:

const bool motorStopped = (bool)(timeSinceLastEvent > maxPulseWidth);

但是,对每个布尔条件都执行此操作非常难看。我想知道是否有一种方法可以配置 Keil uVision / ARM 编译器(或修改我的代码)以不生成有关 bool 的警告,而不会完全禁用有关将枚举类型与其他类型混合的警告。

这些是我可用于配置编译器的选项:

【问题讨论】:

  • 为什么不 typedef bool as int?
  • @Ctx 不是一个坏主意,这个“types.h”文件还有typedef unsigned char boolean; 以及TRUEFALSE。将我所有的 bools 切换为 booleans 似乎是最好的主意。
  • 我能问一下为什么这个问题被否决了吗?
  • 1) 如果您不想这样做,那很好 - 其他人可能想查看该文件 2) 版权位于该文件的顶部,并表示只要版权是再分发就可以包括但不用于背书
  • C89 不是标准 C。它被编译为 C99(也不是标准,但可能是您使用专有商业编译器获得的最好的)。

标签: c arm keil armcc


【解决方案1】:

感觉很脏,但我通过修改 SDK 工具包随附的 types.h 文件解决了这个问题,使其包含 stdbool.h 而不是定义自己的 bool 类型。重新编译我的项目在使用 bool 的第三方代码或我自己的代码中都没有产生警告/错误。

为了更好地衡量,我尝试以某种方式对其进行修改,如果它在 C89 项目中编译,它仍然可以工作:

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#endif

// ...

#if __STDC_VERSION__ < 199901L
typedef enum _bool 
{ 
  false = 0, 
  true = 1 
} bool;
#endif

【讨论】:

    【解决方案2】:

    首先,这些定义在 C 语言中逻辑上是不正确的。

    C 将false 定义为零,将true 定义为非零,其中当然包括 1,但不仅如此。在许多情况下可能很危险:

    只有当函数的返回值为1 时,表达式if(GetValue() == true) 才会计算为真。这是极其危险的,并且可能是许多难以发现的错误的根源。

    bool 可以有任何值,因为int 是它后面的类型。

    铸造不会改变任何东西:

    #include <stdio.h>
    #include <string.h>
    
    typedef enum _bool 
    { 
      false = 0, 
      true = 1 
    } bool;
    
    int main(void) {
    
        bool x;
    
        x = 50;
        printf("%d\n", x);
    
        x = (bool)50;
        printf("%d\n", x);
    }
    

    https://ideone.com/nNHPLg

    您将显式地将 int 值转换为零或一。例如:

    bool x = !!something;

    bool x = something ? true : false;

    【讨论】:

    • 根据标准true 是一个扩展为整数常量 1 类型为int 的宏。 false0。所以,true 实际上是1,而不是“不是0”。您将宏和_Bool 标准类型与复合语句分别解释条件结果的方式混淆了。条件运算符。您显示的代码清楚地表明了什么s wrong with the typedef。 (bool)50 根据标准计算为 1。 **只能代表01的值。
    • @Olaf - 是的,但最小的 int 类型是 char ,它可以容纳多个 0 和一个。基础类型是整数类型之一。标准说任何非零值都被认为是真,只有逻辑运算的结果才能保证为01
    • @Olaf IMO 定义类型 bool 仅在不允许隐式类型转换的语言(例如 C++)中才有意义。否则与true 的比较可能会给出不正确的结果——就像我的回答一样。
    • @Olaf - 最后我确实回答了定义它的特定问题(它不是 stdint.h 中的 bool 类型)
    • 代码符合 C99,这使我的反对意见有效。 char 是一个 integer txype,而不是 int 类型。在编程中,特别是对于初学者来说,我们应该是精确的。你写了“bool 可以有任何值,因为int 是它背后的类型。”我纠正了这一点,因为这完全是错误的。并且定义 bool 根本没有意义,因为 C99+ 确实有 布尔类型,而标准指定的 boolenum 或任何其他标准类型(即为什么添加它)。试试_Bool b = 50;
    猜你喜欢
    • 1970-01-01
    • 2021-12-24
    • 2015-01-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    相关资源
    最近更新 更多