[英]C - Using enum for bit flags - warning: enumerated type mixed with another type
我将枚举常量作为位标志传递给需要枚举类型作为输入的函数,如下所示:
// Enumeration type
typedef enum
{
LED_RED = (1 << 0),
LED_GREEN = (1 << 1),
LED_YELLOW = (1 << 2),
LED_ORANGE = (1 << 3),
} LedType;
...
// Function declaration
void setOnLed(LedType led);
...
// Function call
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
当我调用该函数时,我收到一条警告:
警告:#188-D:枚举类型与另一种类型混合
警告是因为LED_RED | LED_GREEN | LED_YELLOW
LED_RED | LED_GREEN | LED_YELLOW
LED_RED | LED_GREEN | LED_YELLOW
转换为整数,而不是LedType
。
我可以通过向LedType
枚举添加 LED 组合来避免警告,但这意味着我必须添加所有可能的组合......如果我向enum
添加更多 LED 选项,它会变得非常混乱......
我可以使用数组作为函数的输入,但是在调用函数时需要更多的代码,我更喜欢简单的函数调用来设置 LED。
我正在使用 Keil µVision IDE 对基于 ARM 的微控制器 (STM32) 进行编程。
是否有一种简单安全的方法来避免此警告或另一种方法将所有 LED 封装在一个有意义的类型/对象中,以便我可以轻松地将它们传递给函数并在循环中处理它们?
我正在为连接到多个 LED 的基于 ARM 的 MCU 编写程序。 在程序的许多地方,我们将打开/关闭、切换和闪烁 LED 的不同组合。 为了使这个干净和简单,我想编写几个函数,将 LED 的任意组合作为输入,并对所有函数执行相同的操作。
我创建了一个struct
名为LedConfig
与LED和阵列的硬件配置LedConfig
包含每个LED的配置:
typedef struct
{
// Hardware configurations of a LED
...
} LedConfig;
...
LedConfig LedArry[LEDS_LED_COUNT] =
{
[0] = { /* Red LED config */ },
[1] = { /* Green LED config */ },
[2] = { /* Yellow LED config */ },
[3] = { /* Orange LED config */ }
};
现在,我想要一种简单的方法来将几个 LED 传递给一个函数并循环处理它们。
我为每个 LED 创建了许多位标志:
// Number of LED's defined in the system
#define LED_COUNT 4
// LED flags, for usage in LED's function
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_YELLOW (1 << 2)
#define LED_ORANGE (1 << 3)
定义一个函数:
void setOnLed(uint32_t led)
{
uint32_t bitMask = 1;
for(int i = 0; i < LED_COUNT; i++)
{
if(led & bitMask)
{
LedConfig* ledConfig = &LedArry[i];
// Turn on LED ...
}
bitMask <<= 1;
}
}
现在我可以通过按位或操作将 LED 传递给函数:
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
这工作正常,但是...
我更喜欢使用enum
而不是定义 LED 标志,以便将主题封装在一个有意义的类型/对象中。
我用枚举替换了定义:
typedef enum
{
LED_RED = (1 << 0),
LED_GREEN = (1 << 1),
LED_YELLOW = (1 << 2),
LED_ORANGE = (1 << 3),
} LedType;
并修改setOnLed
函数输入以获取枚举类型:
void setOnLed(LedType led)
{
// ...
}
当我用几个 LED 调用函数时:
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
我收到警告:
警告:#188-D:枚举类型与另一种类型混合
注意: uint32_t
来自stdint.h并且是一个无符号的 32 位整数。
我更喜欢使用枚举而不是定义 LED 标志,因为我更喜欢将主题封装在一个有意义的类型/对象中。
这完全没问题,但请记住两件事:
LED_RED
始终是带符号的int
类型。LedType
是实现定义的。 如果使用的值适合一个整数类型,编译器可以选择较小的整数类型。通常,您会希望在嵌入式系统中避免有符号类型,因为整数提升和按位运算符的各种问题。
一个这样的问题是左移有符号整数常量1
。 这是int
类型并有符号,因此在 32 位系统上, 1 << 31
表示未定义的行为错误。 因此,始终为您的整数常量取消符号后缀:始终使用1u << n
而不是1 << n
。
我收到警告:
warning: #188-D: enumerated type mixed with another type
是的,因为该函数需要一个uint32_t
但你传递了一个int
,因为表达式LED_RED | LED_GREEN | LED_YELLOW
中的所有操作数LED_RED | LED_GREEN | LED_YELLOW
LED_RED | LED_GREEN | LED_YELLOW
是int
- 它们是如上所述的枚举常量。 您应该重写该函数以将LedType
作为参数。
例子:
// led.h
typedef enum
{
LED_NONE = 0u,
LED_RED = 1u << 0,
LED_GREEN = 1u << 1,
LED_YELLOW = 1u << 2,
LED_ORANGE = 1u << 3,
LED_ALL = LED_RED | LED_GREEN | LED_YELLOW | LED_ORANGE;
} led_t;
#define LED_PORT PORTX
void set_led (led_t leds);
// led.c
#include "led.h"
void set_led (led_t leds)
{
// this assuming you'll want to use the function both to set and clear leds
uint32_t led_port = LED_PORT;
led_port &= (uint32_t) ~LED_ALL;
led_port |= (uint32_t) leds;
LED_PORT = (uint32_t) leds;
}
(uint32_t)
强制转换严格来说不是必需的,但会满足迂腐的编译器和 MISRA-C 检查器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.