一个元素的结构是否与元素本身兼容?

时间:2012-01-23 11:34:27

标签: c++ c++11

如果我有以下结构:

struct Foo { int a; };

代码是否符合C ++标准?我的意思是,它不能产生“未定义的行为”吗?

Foo foo;
int ifoo;

foo = *reinterpret_cast<Foo*>(&ifoo);

void bar(int value);

bar(*reinterpret_cast<int*>(&foo));

auto fptr = static_cast<void(*)(...)>(&bar);
fptr(foo);

3 个答案:

答案 0 :(得分:10)

9.2 / 20在N3290中说

  

指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然。

你的Foo是一个标准布局类。

所以你的第二次演员是正确的。

我不能保证第一个是正确的(并且我使用的架构中,char的对齐限制比仅包含char的结构更弱,在这样的架构上,这将是有问题的)。标准的保证是,如果你有一个指向int的指针,它真正指向结构的第一个元素,你可以将它重新解释为指向结构的指针。

同样地,如果它是re​​interpret_cast,我看不到任何可以使你的第三个被定义的东西(我很确定一些ABI使用不同的约定来传递结构和基本类型,所以它非常可疑,我需要一个在标准中明确提到接受它)并且我很确定在指向函数的指针之间什么都不允许static_cast。

答案 1 :(得分:4)

只要您只访问结构的第一个元素,它就被认为是安全的,因为在结构的第一个成员之前没有填充。实际上,这个技巧例如在Objecive-C运行时中使用,其中泛型指针类型定义为:

typedef struct objc_object {
    Class isa;
} *id;

并且在运行时,真正的对象(仍然是裸结构指针)具有这样的内存布局:

struct {
    Class isa;
    int x; // random other data as instance variables
} *CustomObject;

并且运行时使用此方法访问实际对象的类。

答案 2 :(得分:2)

Foo是一种普通的旧数据结构,这意味着它只包含您明确存储在其中的数据。在这种情况下:一个int。 因此int和Foo的内存布局是相同的。

你可以毫无问题地从一个到另一个进行类型转换。使用这种东西是一个聪明的想法是一个不同的问题。

PS: 此通常有效,但不一定是由于不同的对齐限制。见AProgrammer的答案。