只读内存映射寄存器在C中用`volatile const`定义,但在C++中只用`volatile`定义

JAB*_*JAB 6 c c++ embedded cmsis

在使用Atmel SAM3X8E处理嵌入式系统项目时,我注意到某些CMSIS头文件中的以下代码.

#ifndef __cplusplus
typedef volatile const uint32_t RoReg; /**< Read only 32-bit register (volatile const unsigned int) */
#else
typedef volatile       uint32_t RoReg; /**< Read only 32-bit register (volatile const unsigned int) */
#endif
Run Code Online (Sandbox Code Playgroud)

为什么C++的typedef不包含const?我在某处看到C++没有在运行时内存中存储整数const变量,如果为true则意味着const由于微控制器寄存器的内存映射方式需要删除它,但我似乎无法找到其他任何说法C++就是这样做的(尽管我的搜索非常简短).我没有太多的C++经验,我也认为可能是C++不允许使用conststruct成员,因为那些typedef主要用于struct typedef中的寄存器集合,但似乎也不是这样.

Fel*_*tti 5

如果用const声明,C++标准将强制您初始化变量的内容.在微控制器寄存器的情况下,您不希望这样做.

  • 虽然这可能是答案的一部分,但是在这里提出的情况中,我怀疑编译器是否有责任"保留空间",因为所讨论的寄存器很可能是处理器/片上外设的固定位置硬件功能.可能typedef只用于声明指向这样一个寄存器的指针. (5认同)
  • 当然,@ fanl给出的理由可能_still_是确切的原因,即使它不适用,因为只使用了指向类型的指针.该标题的作者很可能具有这种确切的推理(无论它是否适用于实践).至少,这是一个似是而非的推理.编译器仍然可以解决它的事实并不一定意味着人类不会错. (2认同)
  • @DKrueger - 在某些其他情况下可能是合理的,但CMSIS在头文件中明确定义了地址. (2认同)

D K*_*ger 3

因为没有RoReg对象被实例化,所以没有充分的理由省略consttypedef 中的限定符。

每次使用RoReg都在定义指向类型的指针的宏中......

#define REG_WDT_SR (*(RoReg*)0x400E1A58U) /**< \brief (WDT) Status Register */
Run Code Online (Sandbox Code Playgroud)

...或struct使用类似宏访问的声明。

typedef struct {
  WoReg WDT_CR; /**< \brief (Wdt Offset: 0x00) Control Register */
  RwReg WDT_MR; /**< \brief (Wdt Offset: 0x04) Mode Register */
  RoReg WDT_SR; /**< \brief (Wdt Offset: 0x08) Status Register */
} Wdt;

#define WDT        ((Wdt    *)0x400E1A50U) /**< \brief (WDT) Base Address */
Run Code Online (Sandbox Code Playgroud)

即使使用const限定符,代码在 C 和 C++ 中的行为也应该相同。

也许作者误解了这个标准。为了保证 C++ 结构具有与 C 中相同的布局,它要求类“对所有非静态数据成员具有相同的访问控制(第 11 条)”。作者可能将const和误认为volatile是访问控制说明符。如果是,那么您会希望所有结构成员具有相同的 cv 限定符,以确保 C 和 C++(以及硬件)布局之间的兼容性。public但它protected定义private了访问控制。