简体   繁体   English

在C ++中将结构指针转换为联合指针

[英]casting structure pointer to union pointer in C++

I have a Union containing various struct member. 我有一个包含各种struct成员的Union。

union U {
    struct S1 as_s1;
    struct S2 as_s2;
    …
};

How can I cast pointer to struct as_s1 to a pointer to union U in C++? 如何在C ++中将struct as_s1的指针转换为Union U的指针?

I know because of this that it can be easily done using C casting. 我知道是不是因为这个 ,它可以用C铸造轻松完成。 But I want to use the feature of Advance class type casting of C++ without causing any errors. 但是我想使用C ++的Advance类类型转换的功能而不会引起任何错误。

From the standard 6.9.2.4. 来自标准6.9.2.4。

Two objects a and b are pointer-interconvertible if: 如果满足以下条件,则两个对象a和b是指针可互换的

  1. they are the same object, or 它们是同一对象,或者
  2. one is a standard-layout union object and the other is a non-static data member of that object (12.3), 一个是标准布局联合对象,另一个是该对象的非静态数据成员(12.3),
  3. one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, the first base class subobject of that object (12.2), or 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则是该对象的第一个基类子对象(12.2),或者
  4. there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible. 存在一个对象c,使得a和c是指针可互换的,而c和b是指针可互换的。

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast (8.2.10). 如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过reinterpret_cast(8.2.10)从指向另一个的指针获得指向一个的指针。

This means that you can convert them to each other using reinterpret_cast . 这意味着您可以使用reinterpret_cast将它们彼此转换。 However, you cannot access the memory of wrong type. 但是,您不能访问错误类型的内存。 Eg, following is a well-defined code: 例如,以下是定义良好的代码:

#include <iostream>

struct S1 {
  int i;
};

struct S2 {
  short int i;
};

union U {
  struct S1 as_s1;
  struct S2 as_s2;
};

void printUnion(U* u, int type) {
  if (type == 0){
    S1 *s1 = reinterpret_cast<S1*>(u);
    std::cout << s1->i << std::endl;
  } else {
    S2 *s2 = reinterpret_cast<S2*>(u);
    std::cout << s2->i << std::endl;
  }
}

int main() {
  S1 s1{1};
  printData(reinterpret_cast<U*>(&s1), 0);
  S2 s2{2};
  printData(reinterpret_cast<U*>(&s2), 1);
}

But, if you give a wrong type parameter to the printData -function, the behavior is undefined. 但是,如果您给printData一个错误的类型参数,则该行为是不确定的。

In c++ it is hard to imagine a program with a good design where the cast would be needed. 在c ++中,很难想象一个需要良好设计的程序将需要强制转换。 In c if you already have a need for a union object there might be a case where this could be used to implement polymorphism (of course no reinterpret_cast there). 在c中,如果您已经需要并集对象,则可能会用它来实现多态(当然那里没有reinterpret_cast)。 Though it is usually done with void* . 虽然通常是用void*完成的。

The proper casting for such pointer casts is reinterpret_cast: 此类指针转换的正确转换为reinterpret_cast:

#include <stdio.h>

struct S1 {
  int x,y;
};

struct S2 {
  double a,b;
};

union U {
  struct S1 as_s1;
  struct S2 as_s2;
};

int main() {

  struct S1 mys1;

  union U *uptr  = reinterpret_cast<union U*>(&mys1);
  uptr->as_s1.x = 42;
  printf("%d\n",mys1.x);

  return 0;
}

Beware that since sizeof(struct S1) < sizeof(struct S2) , in this example, and you only allocated enough memory for the size of S1 , if you try to do anything on uptr->as_s1.b you will corrupt the stack. 请注意,在本示例中,由于sizeof(struct S1) < sizeof(struct S2) ,并且您仅分配了S1大小的足够内存,因此,如果尝试在uptr->as_s1.b上执行任何操作,则会破坏堆栈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM