我正在编译一个 C++ 程序以在独立环境中运行,并且我正在运行的 CPU 定义了一个可用的 32 位外设寄存器(编辑:内存映射) at 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 消毒器的设备。
我看过[基本.stc.动态.安全 http://eel.is/c++draft/basic.stc.dynamic.safety] and [basic.compound#def:object_pointer_type http://eel.is/c++draft/basic.compound#def:object_pointer_type] 但这似乎只限制了指向动态对象的指针的有效性。我认为它不适用于这段代码,因为“对象”位于PERIPH_ADDRESS
从未被假定为动态的。我想我可以有把握地说,由p
永远不会到达其存储期限的末尾,可以考虑static.
我也看过为什么 C++ 不允许从有效地址和类型创建有效指针? https://stackoverflow.com/questions/53200002/why-does-c-disallow-the-creation-of-valid-pointers-from-a-valid-address-and-ty以及对该问题的回答。它们也只引用动态对象的地址及其有效性,因此它们不回答我的问题。
我考虑过但无法回答自己的其他问题可能有助于解决主要问题:
- 我是否会遇到任何 UB 问题,因为该对象从未在 C++ 抽象机中构造过?
- 或者我实际上可以认为该对象是一个具有正确“构造”的静态存储持续时间的对象吗?
显然,我更喜欢引用任何最新 C++ 标准的答案。
指针强制转换的含义是由实现定义的[expr.reinterpret.cast] https://timsong-cpp.github.io/cppwp/expr.reinterpret.cast#5.sentence-2
整型或枚举类型的值可以显式转换为指针。转换为足够大小的整数(如果实现中存在这样的整数)并返回到相同指针类型的指针将具有其原始值;指针和整数之间的映射是由实现定义的。
Therefore this is well-defined. If your implementation promises you the result of the cast is valid, you are fine.†
链接的问题是关于指针算术的,这与当前的问题无关。
† By definition, a valid pointer https://timsong-cpp.github.io/cppwp/basic.compound#3 points to an object, implying subsequent indirections are also well-defined. Care should be exercised in making sure the object is within its lifetime https://timsong-cpp.github.io/cppwp/basic.life#7.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)