当第一个字段未对齐时,在C中铸造结构

时间:2012-04-01 07:26:39

标签: c casting structure

给出c中的两个结构:

typedef struct _X_
{
   int   virtual_a;
   int   virtual_b;
   void *virstual_c;
   int   a;
   int   b;
   void *c;

    /* More fields to follow */
}X;

typedef struct _Y_
{
   int a;
   int b;
   void *c;

   /* Same fields as in X structure */
}Y;
问:这样说是否安全?

void foo_low( Y *y )
{
   y->a = 1;
   y->b = 2;
}

 void foo( X *x )
 {
   Y *y = (Y *)(&(x->a) )

   foo_low( y );
 }

是标准C吗?它会适用于所有编译器吗?填充有问题吗?

3 个答案:

答案 0 :(得分:2)

不,您的功能foo无法正常工作,因为a位置错误。

你的例子显然已经弥补,并且会减少我对你真正试图解决的问题的答案的相关性,但是这个定义确实像我相信你要求的那样:

struct header {
  int a;
  int b;
  void *c;
};

struct shared_fields {
  int a;
  int b;
  void *c;
  /* More fields to follow */
 };

typedef struct 
{
   struct header virtuals;
   struct shared_fields shared;
} X;

typedef struct 
{
   struct shared_fields shared;
} Y;


void foo_low(struct shared *ys)
{
   ys->a = 1;
   ys->b = 2;
}

void foo(X *x)
{
  foo_low(&x->shared);
}

但是,这不会执行演员表,因为不需要演员表。如果你真的打算通过一个结构设置数据并通过另一个结构访问它,那么标准C中不允许这样做(尽管Hubert描述的同一结构与不同标签可能有例外)。

我怀疑对您提出的问题的更好解决方案是使用union,这通常可以用来做您可能想到的事情。但严格来说,如果你有一个联合类型的对象u而你设置了u.a,那么在设置u.b之前访问u.b的值有未定义的行为。虽然人们通常不担心这一点。

答案 1 :(得分:1)

如果两个结构都具有相同的结构,则可以。 struts中字段的名称不必相同,但它们的类型必须相同。 X中的每个子字段必须与其类型和位置中的Y中的子字段匹配。字段名称可以不同。

答案 2 :(得分:1)

那应该有用。但由于你需要以两种不同的方式访问相同的字段(y-> a和x-> a不同),我会使用union:

typedef struct _Y_
{
    int a;
    int b;
    void *c;

   /* Same fields as in X structure */
}Y;


typedef struct _X_
{
     int   virtual_a;
     int   virtual_b;
     void *virstual_c;
     Y    y_fields;     
}X;


typedef union {
    X x;
    Y y;
} Z;

现在x.virtual_a和y.a位于相同的内存地址中。

您可以按如下方式重写代码:

void foo_low( Z *z )
{
   z->y.a = 1;
   z->y.b = 2;
}

void foo( Z *z )
{
   Z *w = z;
   w->y = z->x.y_fields;
   foo_low( w );
}

唯一笨拙的部分是在X中添加Y.