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

时间:2018-03-26 12:52:01

标签: c++ casting

我有一个包含各种结构成员的联盟。

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

如何将指向struct as_s1的指针转换为C ++中指向union U的指针?

我知道因为this可以使用C转换轻松完成。但我想使用C ++的Advance类型转换功能而不会导致任何错误。

2 个答案:

答案 0 :(得分:1)

从标准6.9.2.4开始。

  

如果出现以下情况,则两个对象a和b为指针可互换

     
      
  1. 它们是同一个对象,或
  2.   
  3. 一个是标准布局联合对象,另一个是该对象的非静态数据成员(12.3),
  4.   
  5. 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的第一个基类子对象(12.2) ,或
  6.   
  7. 存在一个对象c,使得a和c是指针可互换的,而c和b是指针可互换的。
  8.         

    如果两个对象是指针可互换的,那么它们具有相同的地址,并且可以通过reinterpret_cast(8.2.10)获得指向另一个指针的指针。

这意味着您可以使用reinterpret_cast将它们相互转换。但是,您无法访问错误类型的内存。例如,以下是明确定义的代码:

#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);
}

但是,如果为printData - 函数提供了错误的类型参数,则行为未定义。

在c ++中,很难想象一个具有良好设计的程序,其中需要使用强制转换。在c中如果你已经需要一个union对象,可能会出现这种情况,可以用来实现多态(当然在那里没有reinterpret_cast)。虽然通常使用void*完成。

答案 1 :(得分:-3)

这种指针强制转换的正确转换是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;
}

请注意,自sizeof(struct S1) < sizeof(struct S2)以来,在此示例中,您只为S1的大小分配了足够的内存,如果您尝试在uptr->as_s1.b上执行任何操作,则会损坏堆栈。