Cam*_*ind 9 casting volatile c++11 c++17
在构建用于控制嵌入式微处理器上的硬件的库时,一项常见任务是操作特定内存位置处的位以控制硬件功能。
在 AVR 处理器中,Atmel(现在的 Microchip)提供了扩展为如下的宏:
#define PORTA (*(volatile uint8_t *)(0x25))
Run Code Online (Sandbox Code Playgroud)
这可以实现以下功能:
PORTA |= 1;
Run Code Online (Sandbox Code Playgroud)
现在,在 C++11(及更新版本)中,希望将几乎所有用法替换#define为constexpr。
在旧版本的 GCC C++ 编译器 (4.9.2) 中,编译了以下内容:
#include <avr/io.h>
constexpr volatile uint8_t *const PortA = &PORTA;
Run Code Online (Sandbox Code Playgroud)
在8.2.0版本中,上面的代码无法编译并给出错误:
error: 'reinterpret_cast<volatile uint8_t* {aka volatile unsigned char*}>(37)' is not a constant expression
Run Code Online (Sandbox Code Playgroud)
我不是在寻找解释为什么不能reinterpret_cast在constexpr上下文中使用或者为什么整数到指针的转换是非法的。
在现代 C++ 中拥有constexpr指向内存的指针的正确方法是什么?volatile
我见过一些建议,将 a 的内存地址存储PORTA在 a 中constexpr uintptr_t,然后在运行时reinterprect_cast进行位volatile uint8_t * const操作。
例如,这可以工作,甚至可以按预期编译为单个sbi指令。avr-gcc
#include <stdint.h>
constexpr uintptr_t PortA = 0x25;
void set() { *((volatile uint8_t *)(PortA)) |= 1; }
Run Code Online (Sandbox Code Playgroud)
然而,它需要相当数量的丑陋的样板才能用作PortA它的预期指针。
这也存在一个问题,就是似乎无法PORTA直接使用宏。相反,我们被迫对内存地址进行硬编码0x25,这破坏了某些理想的可移植性功能。
感觉就像我错过了一些明显的东西,因为我的搜索没有产生任何成果。
例如,这感觉像是一个“地址常量表达式”,但这似乎与引用静态分配的值有关,const这并不完全是我想要的。
const char str[] = "FooBar";
constexpr const char * x = str + 2;
Run Code Online (Sandbox Code Playgroud)
您无法创建由非常量表达式初始化的 constexpr 指针。但是,您可以创建一个static const指针:
static uint8_t volatile* const PortA = &PORTA;
Run Code Online (Sandbox Code Playgroud)
或者,更好的是,static参考:
static uint8_t volatile& PortA = PORTA;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
498 次 |
| 最近记录: |