ARM C++编译器不会编译具有可变常量成员的结构
ARM C++ compiler won't compile structure with volatile const member
我正在尝试为 ARM MCU 目标编译C++代码,其中包括一个寄存器定义头文件。我收到以下错误:
test.h(18): error: #294: invalid union member -- class "struct <unnamed>::<unnamed>::<unnamed>" has a disallowed member function
该错误仅在编译 C++ 项目时发生,而不是在编译 C 项目时发生。
它是由以下结构的__IM
(volatile const
(成员引起的:
typedef struct {
union {
__IOM uint32_t VAR;
struct {
__IOM uint32_t BIT0 : 1;
__IOM uint32_t BIT1 : 1;
__IOM uint32_t BIT2 : 1;
__IM uint32_t TBD : 13;
__IOM uint32_t BIT17 : 1;
} VAR_b;
} ;
} VAR_Type;
这里解释了为什么这些__IM
成员应该是volatile const
,即使在C++:
http://www.keil.com/support/docs/3687.htm
我正在使用带有默认ARM编译器的Keil uVision:
*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:Keil_v5ARMARMCCBin'
如果不破解MCU.h
文件以重新定义__IM
以volatile
(不是volatile const
(,我找不到解决此问题的方法
#undef __IM
#define __IM volatile
添加前面的代码解决了问题并允许我进行编译,但 MCU 制造商提供的MCU.h
文件不应该被修改,所以我想找到一个更干净的解决方案。
您看到的错误与 g++ 在 C++03 模式下输出的错误最相似。即,对于以下代码
#include <stdint.h>
#define __IOM volatile
#define __IM volatile const
typedef struct {
union {
__IOM uint32_t VAR;
struct {
__IOM uint32_t BIT0 : 1;
__IOM uint32_t BIT1 : 1;
__IOM uint32_t BIT2 : 1;
__IM uint32_t TBD : 13;
__IOM uint32_t BIT17 : 1;
} VAR_b;
} ;
} VAR_Type;
int main()
{
VAR_Type x={0};
}
我得到以下编译结果:
$ g++ test.cpp -o test -pedantic-errors -std=c++03
test.cpp:15:7: error: member ‘<unnamed struct>::<unnamed union>::<unnamed struct> <unnamed struct>::<unnamed union>::VAR_b’ with copy assignment operator not allowed in union
} VAR_b;
^~~~~
test.cpp:15:7: note: unrestricted unions only available with -std=c++11 or -std=gnu++11
问题是联合内部的结构没有任何复制赋值运算符,因为它的格式不正确(不能分配给const
成员(。有关详细信息,请参阅此 SO 答案。由于(我想(您无法编辑标头,因此您可能希望在 C++11 模式下使用启用了 C++11 的编译器。不确定凯尔是否有。
我无权访问 Keil 编译器,但在 g++ 7.4.0 下,此结构生成的错误不是在定义它的地方,而是在实例化它的地方。
即 该行
VAR_Type fred;
导致错误,因为const
成员需要初始化器(作为位字段,不能指定为默认初始化器,因此只能通过默认构造函数定义提供(。
你自己实例化这个结构吗?(也许在第 18 行?
如果是,并且您这样做是出于合法原因(例如,为了硬件寄存器的内存副本(,似乎确实有一个解决方案:
VAR_Type fred = { 0 };
编译没有错误(至少使用 G++ 7.4.0(。 (请注意,这通过联合的第一个成员初始化结构。
[编辑添加:一个包含完整编译器命令行的最小完整可验证示例将使人们更容易帮助您。
非常感谢您的帮助!
我可以联系到 ARM 支持。这似乎是他们的SVDconv工具和ARM编译器v5(又名"armcc"(生成的头文件之间不兼容的真正问题。解决方案是使用 ARM 编译器 v6(又名"armclang"(构建项目。
这些结构不是用户实例化的,因为它们是普通的 C。它们允许轻松访问MCU寄存器。以下是如何在制造商提供的标头中声明它们的示例:
typedef struct { /*!< (@ 0x42000000) GPIOA Structure */
union {
__IOM uint32_t CTRL; /*!< (@ 0x00000000) Control register */
struct {
__IM uint32_t RES : 1;
__IOM uint32_t RST : 1; /*!< [1..1] Soft reset */
__IOM uint32_t INTEN : 1; /*!< [2..2] Interrupt enable */
} CTRL_b;
} ;
union {
__IOM uint32_t IRQPOLSET; /*!< (@ 0x00000004) Interrupt polarity set register */
struct {
__IOM uint32_t P0 : 1; /*!< [0..0] Pin 0 */
__IOM uint32_t P1 : 1; /*!< [1..1] Pin 1 */
__IOM uint32_t P2 : 1; /*!< [2..2] Pin 2 */
__IOM uint32_t P3 : 1; /*!< [3..3] Pin 3 */
__IOM uint32_t P4 : 1; /*!< [4..4] Pin 4 */
__IOM uint32_t P5 : 1; /*!< [5..5] Pin 5 */
__IOM uint32_t P6 : 1; /*!< [6..6] Pin 6 */
__IOM uint32_t P7 : 1; /*!< [7..7] Pin 7 */
__IOM uint32_t P8 : 1; /*!< [8..8] Pin 8 */
__IOM uint32_t P9 : 1; /*!< [9..9] Pin 9 */
__IOM uint32_t P10 : 1; /*!< [10..10] Pin 10 */
__IOM uint32_t P11 : 1; /*!< [11..11] Pin 11 */
__IOM uint32_t P12 : 1; /*!< [12..12] Pin 12 */
__IOM uint32_t P13 : 1; /*!< [13..13] Pin 13 */
__IOM uint32_t P14 : 1; /*!< [14..14] Pin 14 */
__IOM uint32_t P15 : 1; /*!< [15..15] Pin 15 */
} IRQPOLSET_b;
} ;
[etc...]
} GPIO_Type;
下面是一个如何定义第一个对应寄存器的物理地址的示例:
#define GPIOA_BASE 0x41000000UL
这是用户将在其代码中使用的名称的链接:
#define GPIOA ((GPIO_Type*) GPIOA_BASE)
因此,为了访问 IRQPOLSET 电阻器的位 P10,他这样做:
GPIOA->IRQPOLSET_b.P10
- 私有类型的静态常量成员
- constexpr构造函数需要常量成员函数时出现问题
- Clang 格式 10.0 与 5.0 常量成员函数的格式不同
- 为什么"具有常量成员的结构"类型的指针不能指向"具有非常量成员的结构"?
- 常量成员函数中成员变量的类型
- 如何处理运算符=中的常量成员?
- 常量成员和没有setter的私有成员之间有什么区别
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 移动具有常量成员的类的构造和分配
- ARM C++编译器不会编译具有可变常量成员的结构
- 强制在编译时计算类的类的常量成员
- 类中常量成员函数的 c++ 链接错误
- 为什么常量成员可以初始化两次?
- 专用常量成员函数的成员检测
- 与其他静态const成员初始化静态常量成员
- 具有静态和常量成员变量的对象
- 结构中的常量成员即使在初始化后也返回 0
- 在非常量成员函数中,为什么点这个非常量,而 decltype 指针这是常量
- 有没有一种通用方法来"unprotect"静态常量成员?
- 如何初始化共享复杂初始化代码的多个常量成员变量?