较新版本的GCC抛出reinterpret_cast错误

Newer version of GCC throws reinterpret_cast error

本文关键字:cast 错误 reinterpret 抛出 新版本 GCC      更新时间:2023-10-16

我正在开发一个嵌入式项目(在STM32上)。我目前使用GCC 4.9.2,但我想切换到我的工具链的新版本。不幸的是,我在gcc 4.9.2上成功编译的代码在版本6.2.0或7.2.0上抛出了reinpreped_cast错误,我不知道为什么。新的gcc在将int转换为指针并返回到int时似乎遇到了一些问题——我认为这应该是非常正常的操作。

抛出错误消息:

1>STM32L4CMSISstm32l4a6xx.h(1567,30): error : 'reinterpret_cast<ADC_TypeDef*>(1342439424)' is not a constant expression
1>          #define ADC1                ((ADC_TypeDef *) ADC1_BASE)
1>                                       ^
1>         SourcesCAdc.cpp(31,35): note:  in expansion of macro 'ADC1'
1>             case reinterpret_cast<uint32_t>ADC1: u32DMAChannel = LL_DMA_CHANNEL_1; break;

这是我的代码的一部分,错误指的是:

switch ((uint32_t)adc)
{
case (uint32_t)ADC1: u32DMAChannel = LL_DMA_CHANNEL_1; break;
case (uint32_t)ADC2: u32DMAChannel = LL_DMA_CHANNEL_2; break;
case (uint32_t)ADC3: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}

adc声明:

private:
ADC_TypeDef *adc;

以下是所有宏的定义:

#define PERIPH_BASE           (0x40000000UL) /*!< Peripheral base address */
#define AHB2PERIPH_BASE       (PERIPH_BASE + 0x08000000UL)
#define ADC1_BASE             (AHB2PERIPH_BASE + 0x08040000UL)
#define ADC1                  ((ADC_TypeDef *) ADC1_BASE)

所以对于编译器来说,我的开关内转换如下:

(uint32_t)((ADC_TypeDef *) (((0x40000000UL)+ 0x08000000UL)+ 0x08040000UL))

简单地将unsigned long强制转换为某个结构指针并返回到unsigned long。它怎么了?我该怎么做才能消除这个错误?任何宏版本对我来说都是不可能的,因为这些都是BSP库。

不是重新解释失败,而是重新解释的值不被视为常量,因此不能用作事例标签。

事例标签必须是常量表达式,常量表达式是可以在编译时求值的任何表达式。在C++中,reinterpret_cast表达式的求值不是常量表达式

这里的编译器行为变化似乎是编译器将以前的强力C样式转换转换为限制性更强的C++reinterpret_cast。在https://www.onlinegdb.com/显示,当使用C++17编译而不是C++14时,就会出现这种行为,因此简单的"无代码更改"解决方案是将编译设置为早期的标准——可以说,在任何情况下,这都是遗留代码的明智方法,以避免任何其他意外或问题。

然而,stm32l4a6xx.h标头似乎已经提供了ADC基地址的两种表示,一种是整数(ADCx_BASE),另一种是指针(ADCx)。通常情况下,最好完全避免强制转换,并使用适当的目的表示。在这种情况下:

switch ((uint32_t)adc)
{
case ADC1_BASE: u32DMAChannel = LL_DMA_CHANNEL_1; break;
case ADC2_BASE: u32DMAChannel = LL_DMA_CHANNEL_2; break;
case ADC3_BASE: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}

您可以更改代码以避免在switch:的case中强制转换

switch ((uint32_t)adc)
{
case ADC1_BASE: u32DMAChannel = LL_DMA_CHANNEL_1; break;
case ADC2_BASE: u32DMAChannel = LL_DMA_CHANNEL_2; break;
case ADC3_BASE: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}