通过指向班级第一个成员的指针访问成员是不确定的行为吗?

Is it undefined behavior to access members through a pointer to the first member of the class

本文关键字:成员 不确定 访问 指针 第一个      更新时间:2023-10-16

我正在玩一堂课,我想用operator[]索引其中,同时也能够访问字段。

我已经在我想做的事情下附加了一个mcve,它可以通过变量本身访问成员变量,还可以使用一些指针偏移(例如:如果有ab,然后,我可以通过名称访问b,或者如果它们的类型相同,并且在没有填充的情况下使用&a + 1,则可以访问它。

)。

我担心我会遇到不确定的行为,并且不会知道。最初,我试图进行"与1)浮子成员以及2)浮子数组进行结合",但我发现这是不确定的行为。如果我要在下面要做的事情是未定义的,但找不到它(这显然并不意味着它不存在,我很容易错过它)。

由于我也使用CRTP来做到这一点,所以我认为我要自行施放,只要继承不提供任何成员。

为了确保在C 中可能是合法的,我添加了一堆静态断言:

  • 确保它是标准布局,因此我可以将Offsetof用于其他静态断言static_assert(std::is_standard_layout_v<Color>);
  • 确保这是微不足道的static_assert(std::is_trivial_v<Color>);
  • 确保偏移是顺序的static_assert(offsetof(Color, r) == 0);static_assert(offsetof(Color, g) == sizeof(float));static_assert(offsetof(Color, b) == 2 * sizeof(float));
  • 确保从继承static_assert(sizeof(Color) == 3 * sizeof(float));
  • 中添加任何内容

代码:

#include <iostream>
using namespace std;
template <typename T>
class ColorCRTP {
    T& getInstance() {
        return *static_cast<T*>(this);
    }
public:
    // Is it UB to do this when we set values from the
    // fields themselves in the actual class?
    float& operator[](size_t index) {
        // Assume the inheriting class *always* is only a
        // series of sequential members of the exact same
        // type.
        return *(&getInstance().r + index);
    }
};
struct Color : ColorCRTP<Color> {
    float r;
    float g;
    float b;
    Color() = default;
    Color(float r, float g, float b) : r(r), g(g), b(b) { }
};
// Do these help guarantee that I am not performing UB?
static_assert(std::is_standard_layout_v<Color>);
static_assert(std::is_trivial_v<Color>);
static_assert(offsetof(Color, r) == 0);
static_assert(offsetof(Color, g) == sizeof(float));
static_assert(offsetof(Color, b) == 2 * sizeof(float));
static_assert(sizeof(Color) == 3 * sizeof(float));
int main() {
    Color c{0.5f, 0.75f, 1.0f};
    c.g = 0.123f;        
    cout << c[1] << " = " << c.g << endl;
    c[1] = 0.321f; // This is legal or UB?
    cout << c[1] << " = " << c.g << endl;
}

我是否违反了标准并通过执行上述行为来调用不确定的行为?假设当然没有范围的索引。

由于r是第一个成员,我不知道6.7.2第4.3部分是否给我进一步的安慰,因为我是否以安全的方式引用了第一个成员。

程序的行为不确定。

指针算术仅在数组中有效。和rgb不形成数组。

最好的选择是用包含3个标签的switch块回顾float& operator[](size_t)