c++ - 你可以在具有相同表示的类型之间进行reinterpret_cast吗?

标签 c++ language-lawyer undefined-behavior strict-aliasing reinterpret-cast

假设我们有两种类型,它们具有相同的表示形式(相同的成员变量和基类,顺序相同)。它们之间的 reinterpret_cast 是否有效(即不是 UB)?例如。从 MaryAshley&reinterpret_cast 有效吗?如果这两种类型是多态的怎么办?

struct Mary {
    int  m1;
    char m2;
};

struct Ashley {
    int  a1;
    char a2;
};

int TryTwins ()
{
    Mary mary = {};

    Ashley& ashley = reinterpret_cast<Ashley&> (mary);
    ashley.a1 = 1;
    ashley.a2 = 2;

    return mary.m1 + mary.m2;
}

如果我们知道源类型以目标类型的成员变量开头,那么我们将对象的开头转换为另一种类型会怎样?例如。这是有效的(即不是 UB)吗?

struct Locomotive {
    int    engine;
    char   pantograph;
};

struct Train {
    int    engine;
    char   pantograph;
    int*   wagon1;
    int**  wagon2;
    int*** wagon3;
};

int TryTrain ()
{
    Train train = {};

    Locomotive& loc = reinterpret_cast<Locomotive&> (train);
    loc.engine     = 1;
    loc.pantograph = 2;

    return train.engine + train.pantograph;
}

请注意,所有主要编译器都将这些视为有效的强制转换 ( live demo )。问题是,C++ 语言是否允许这样做。

最佳答案

[expr.reinterpret.cast]/11 :

A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_­cast. The result refers to the same object as the source glvalue, but with the specified type. [...]

MaryAshley 是对象类型,因此指向它们的指针可以相互转换。现在,我们使用 Ashley 类型的左值来访问底层 Mary 对象。

[basic.lval]/8 :

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,

  • a cv-qualified version of the dynamic type of the object,

  • a type similar to the dynamic type of the object,

  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,

  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,

  • an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,

  • a char, unsigned char, or std​::​byte type.

这些都不涵盖有问题的情况。 (“类似”谈论简历资格。)因此,未定义的行为。

关于c++ - 你可以在具有相同表示的类型之间进行reinterpret_cast吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58595488/

相关文章:

c++ - `*--p` 在 C++03 中实际上是否合法(格式正确)

c++ -++x %= 10 在 C++ 中是否明确定义?

c++ - 编译器或定义行为的可能优化

c++ - 使用 C++ 构造函数时什么时候必须使用 'this'?

c++ - 如何从特定位置开始读取文件 C++

c++ - 我可以取消引用std::string.end()吗?

c - 设置为 CHAR_MAX 的字符值是否保证环绕到 CHAR_MIN?

c++ - 为什么与 printf 未定义行为中的转换说明符不匹配的参数?

c++ - 如何使用 QString 数组调用 QMetaMethod?

c++ - 从指针转换为对象 C++