如何拥有指向 CMSIS 定义的硬件外设的 constexpr 指针?

问题描述

为了类型安全和命名空间功能,我想尽可能使用 constexpr 而不是 #define

不幸的是,我在尝试时得到了这个 error: 'reinterpret_cast<SPI_TypeDef*>(1073756160)' is not a constant expression

#include <stm32f0xx.h> // #defines SPI2 as pointer to a struct of volatile unsigned ints

constexpr auto myPort = SPI2;

想要解释为什么 reinterperet_cast 不能用在 constexpr 中。

使用 constexpr 指针指向某些内存映射硬件的现代 C++ 方法是什么?

这样做的一个原因是在模板代码中使用这些 constexpr 值。

解决方法

constexpr 代码不是为了避免使用 #define 而发明的;它在那里,所以你可以用表达式做一些你不能做的事情。例如,您可以将 constexpr 指针或整数作为模板参数传递,因为它们是常量表达式。

基本上,任何 constexpr 变量或函数的主要目的是能够在编译时编程中使用。因此,将变量声明为 constexpr 就是说“这是一个编译时常量,在编译时使用它是合理的。”

不能在编译时使用值为任意地址的指针。所以将这样的指针标记为编译时值是一个矛盾。所以你不允许这样做。 constexpr 指针必须是真正的指针,要么是空指针,要么指向实际对象。不是任意地址。

,

这不可能。甚至 std::bit_cast 在某些情况下可以在编译时模拟 reinterpret_cast,当涉及的类型之一是指针时 loses its constexpr-ness

,

就像其他答案已经说明的那样,任意指针是不可能的。

如果它是“为了类型安全和命名空间特性 [...] 到一些内存映射硬件”,你为什么不直接使用

// assumed preconditions,since not provided in question
typedef struct {
  volatile unsigned int a;
  volatile unsigned int b;
} SPI_TypeDef;

SPI_TypeDef* SPI2 = (SPI_TypeDef*)0x12345678;

// actual answer
SPI_TypeDef* const myPort = SPI2;

这样你的指针 myPort 指向一些结构体SPI_TypeDef 类型的数据是常量,而不是指向的结构体。

const 关键字通常是“左分配”。