c++ - 通过预定义的静态地址访问寄存器是 C++ 中未定义的行为吗?

标签 c++ language-lawyer undefined-behavior volatile memory-mapping

我正在编译一个在独立环境中运行的 C++ 程序,我正在运行的 CPU 定义了一个可用的 32 位外围寄存器(编辑:内存映射)在 PERIPH_ADDRESS(正确对齐,不与任何其他 C++ 对象、堆栈等重叠)。

我使用预定义的 PERIPH_ADDRESS 编译以下代码,然后将其与完整程序链接并运行。

#include <cstdint>

struct Peripheral {
    const volatile uint32_t REG;
};

static Peripheral* const p = reinterpret_cast<Peripheral*>(PERIPH_ADDRESS);

uint32_t get_value_1() {
    return p->REG;
}

static Peripheral& q = *reinterpret_cast<Peripheral*>(PERIPH_ADDRESS);

uint32_t get_value_2() {
    return q.REG;
}

extern Peripheral r;
// the address of r is set in the linking step to PERIPH_ADDRESS

uint32_t get_value_3() {
    return r.REG;
}

是否有任何 get_value 函数(直接或通过 p/q)有未定义的行为?如果是,我可以修复它吗?

我认为一个等价的问题是:任何符合标准的编译器都可以拒绝为我编译预期的程序吗?例如,打开了 UB sanitizer 的一个。

我看过[ basic.stc.dynamic.safety ] 和 [ basic.compound#def:object_pointer_type ] 但这似乎只限制了指向动态对象的指针的有效性。我认为它不适用于这段代码,因为 PERIPH_ADDRESS 中的“对象”从未被假定为动态的。我想我可以有把握地说,p 表示的存储永远不会达到其存储持续时间的终点,它可以被视为静态

我也看过 Why does C++ disallow the creation of valid pointers from a valid address and type?以及对该问题的回答。它们也只引用动态对象的地址及其有效性,所以它们没有回答我的问题。

我考虑过但无法回答自己但可能有助于解决主要问题的其他问题:

  • 我是否遇到任何 UB 问题,因为该对象从未在 C++ 抽象机中构造过?
  • 或者我真的可以将对象视为具有正确“构造”的静态存储持续时间的对象吗?

显然,我更喜欢引用任何最新 C++ 标准的答案。

最佳答案

从指针转换的含义是实现定义的 [expr.reinterpret.cast]

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.

因此这是明确定义的。如果您的实现向您保证强制转换的结果是有效的,那么您没问题。

链接的问题是关于指针运算的,这与手头的问题无关。

†​​ 根据定义,一个 valid pointer指向一个对象,意味着后续的间接寻址也是明确定义的。应注意确保对象是 within its lifetime .

关于c++ - 通过预定义的静态地址访问寄存器是 C++ 中未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213699/

相关文章:

c++ - 防止 Core Dump 使用空指针初始化字符串

c++ - 什么是初始化的子表达式

c++ - 类型删除工作或失败取决于优化级别

c++ - 3点的平面方程式未返回正确值

c++ - 使用 C++ 和 directx 创建地形

c++ - 选择在 Windows 7 上无法正常工作

c - snprintf c 的奇怪行为

c++ - 多线程 Win32 C++ 程序在多线程中使用 try/catch 时崩溃

c++ - 算术运算符是否必须将整数参数提升为 int?

c - 以下 C 代码编译并运行,但它是未定义的行为吗?