首页 > 解决方案 > 左移计数> = C宏中的类型宽度

问题描述

我编写了一个 C 宏来设置/取消设置 uint32 变量中的位。以下是宏的定义:

extern uint32_t error_field, error_field2;
    #define SET_ERROR_BIT(x) do{\
                                if(x < 0 || x >63){\
                                    break;\
                                }\
                                if(((uint32_t)x)<32U){\
                                    (error_field |= ((uint32_t)1U << ((uint32_t)x)));\
                                    break;\
                                } else if(((uint32_t)x)<64U){\
                                    (error_field2 |= ((uint32_t)1U<<(((uint32_t)x)-32U)));\
                                }\
                            }while(0)

    #define RESET_ERROR_BIT(x) do{\
                                if(((uint32_t)x)<32U){\
                                    (error_field &= ~((uint32_t)1U<<((uint32_t)x)));\
                                    break;\
                                } else if(((uint32_t)x) < 64U){\
                                    (error_field2 &= ~((uint32_t)1U<<(((uint32_t)x)-32U)));\
                                }\
                             } while(0)

我正在传递一个枚举字段,如下所示:

enum error_bits {
    error_chamber01_data = 0,
    error_port21_data,
    error_port22_data,
    error_port23_data,
    error_port24_data,
/*this goes on until 47*/
};

产生此警告:

左移计数 >= 类型的宽度 [-Wshift-count-overflow]

我这样称呼宏:

USART2->CR1 |= USART_CR1_RXNEIE;
SET_ERROR_BIT(error_usart2);
/*error_usart2 is 47 in the enum*/
return -1;

我在每个宏中都会收到此警告,即使是左移计数 < 31 的宏。

如果我在没有宏的情况下使用宏的定义,则不会产生警告。行为与 64 位变量相同。我正在使用 AC6 STM32 MCU GCC 编译器对 STM32F7 进行编程。我不明白为什么会这样。谁能帮我?

标签: cgccmacrosstm32

解决方案


如 M Oehm 所述,可能是编译器无法正确诊断的问题。一种解决方法可能是,而不是使用减号运算,而是使用余数运算:

#define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
#define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
#define _SET_ERROR_BIT(x) do{\
                            if((x)<32U){\
                                SET_BIT(error_field, x);\
                            } else if((x)<64U){\
                                SET_BIT(error_field2, x);\
                            }\
                        }while(0)
#define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))

这样编译器终于足够聪明,知道 的值x永远不会超过 32。

对“_”宏的调用用于强制x始终为 uint32_t,无条件地调用宏,避免使用负值的调用的 UB x

大肠杆菌中测试


推荐阅读