较新版本的GCC引发reinterpret_cast错误

时间:2019-01-05 22:20:34

标签: c++ gcc casting embedded stm32

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

抛出错误消息:

1>STM32L4\CMSIS\stm32l4a6xx.h(1567,30): error : 'reinterpret_cast<ADC_TypeDef*>(1342439424)' is not a constant expression
1>          #define ADC1                ((ADC_TypeDef *) ADC1_BASE)
1>                                       ^
1>         Sources\CAdc.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库。

2 个答案:

答案 0 :(得分:3)

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

大小写标签必须是常量表达式,并且常量表达式是可以在编译时求值的任何表达式。在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;
}

答案 1 :(得分:1)

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

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;
}
相关问题