我正在开发一个嵌入式项目(在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库。
答案 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;
}