我正在开发一个嵌入式项目(在STM32上).我目前使用的是GCC 4.9.2,但我想切换到较新版本的工具链.不幸的是,我的代码在gcc 4.9.2上成功编译,在6.2.0或7.2.0版本上引发了reinpreted_cast错误,我也不知道为什么.看来,较新的gcc在将int转换为指针并返回int时遇到了一些问题-我认为这应该是正常的操作.
I am developing an embedded project (on STM32). I currently use GCC 4.9.2, but I would like to switch to newer version of my toolchain. Unfortunately my code which succesfully compiles on gcc 4.9.2, throws reinpreted_cast errors on version 6.2.0 or 7.2.0 and I have no idea why. It looks like that newer gcc sees some problems when casting int to pointer and back to int - which I think should be quite normal operation.
抛出错误消息:
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;这是我的代码的一部分,该错误涉及以下内容:
Here is part of my code which error refers to:
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)因此对于编译器,我的切换中转换如下:
So for compiler, my in-switch cast looks like this:
(uint32_t)((ADC_TypeDef *) (((0x40000000UL)+ 0x08000000UL)+ 0x08040000UL))简单地将 unsigned long 强制转换为某些结构指针,然后返回到 unsigned long .怎么了我应该怎么做才能摆脱这个错误?对我而言,任何宏版本都是不可能的,因为它们是BSP库.
Simple cast of unsigned long to some struct pointer and back to unsigned long. What is wrong with it? Whould should I do to get rid of this error? Any macro edition is impossible for me because these are BSP libraries.
推荐答案不是重新解释失败,而是重新解释的值不视为常量,因此不能用作大小写标签.
It is not the reinterpret that is failing, but rather the reinterpreted value is not regarded as a constant so therefore cannot be used as a case label.
大小写标签必须是常量表达式,而常量表达式是可以在编译时求值的任何表达式.在C ++中,对 reinterpret_cast 表达式的求值不是恒定表达式.
Case labels must be a constant expression, and a constant expression is any expression that can be evaluated at compile time. In C++ evaluation of a reinterpret_cast expression is not a constant expression.
此处的编译器行为发生了变化,即编译器将以前的蛮力C样式转换为限制性更强的C ++ reinterpret_cast .在 www.onlinegdb/上进行的测试表明,在C ++ 17编译时会发生此行为使用的是C ++ 14而不是C ++ 14,因此简单的无代码更改"解决方案是将编译设置为较早的标准-在任何情况下,为避免任何其他意外情况或麻烦,可以说是对旧代码的明智方法.
The compiler behaviour change here appears that the compiler translates the previously brute-force C-style cast into a more restrictive C++ reinterpret_cast. Testing at www.onlinegdb/ shows that this behaviour occurs when C++17 compilation is used but not C++14, so the simple "no code change" solution is to set the compilation to the earlier standard - arguably a sensible approach for legacy code in any case to avoid any other surprises or gotchas.
然而,似乎stm32l4a6xx.h标头已经提供了ADC基址的两种表示形式,一个表示整数( ADCx_BASE ),另一个表示指针( ADCx ).通常最好完全避免强制转换并使用目的的适当表示.在这种情况下:
It seems however that the stm32l4a6xx.h header already provides two representations of the ADC base address one an integer (ADCx_BASE) and the other a pointer (ADCx). It is generally better to avoid casts at all and use the appropriate representation of the purpose. In this 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; }更多推荐
较新版本的GCC引发reinterpret
发布评论