简体   繁体   English

第一个字段未对齐时在C中强制转换结构

[英]Casting of structures in C when first fields are not aligned

Given two structure in c: 在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;

Q : Is it safe to say that ? 问:可以这样说吗?

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

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

   foo_low( y );
 }

Is it standard C ? 是标准C吗? will it work on all compilers ? 它可以在所有编译器上使用吗? Is there any problem with padding ? 填充有问题吗?

No, your function foo won't work, because a is in the wrong place. 不,您的函数foo无法正常工作,因为a放在错误的位置。

Your example is clearly made up and tha's going to reduce the relevance of my answer to the problem you are really trying to solve, but this definition does something like I believe you are asking for: 您的示例很明显,并且将减少我对您确实要解决的问题的回答的相关性,但是此定义的作用类似于我相信您所要求的:

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

However, this does not perform a cast, since one is not needed. 但是,由于不需要,因此不会执行强制转换。 If you really intended to set data via one struct and access it via another, this is not allowed in standard C (though there might be an exception for same-struct-with-different labels as described by Hubert). 如果您确实打算通过一个结构设置数据并通过另一个结构访问数据,则在标准C语言中是不允许的(尽管Hubert所描述的带有不同结构的相同标签可能会有例外)。

I suspect that a better solution to the problem you asked about is the use of union which can often be used to do what you may have in mind. 我怀疑对您提出的问题的更好解决方案是使用union ,该union通常可以用来做您可能想做的事情。 But strictly speaking, if you have an object u of union type and you set ua , accessing the value of ub before setting ub has undefined behaviour. 但是严格来说,如果您具有联合类型的对象u并设置了ua ,则在设置ub之前访问ub的值具有未定义的行为。 Though commonly people do not worry about that. 尽管通常人们并不为此担心。

if both structs have identically structure it is ok. 如果两个结构具有相同的结构,则可以。 Names of fields inside the struts need not to be the same, but their types must be the same. 支撑内部的字段名称不必相同,但它们的类型必须相同。 Each subfield in X must match to a subfield in Y in its type and position. X中的每个子字段在类型和位置上都必须与Y中的一个子字段匹配。 Names of fields can be different. 字段名称可以不同。

That should work. 那应该工作。 But since you need to access the same fields in two distinct ways (y->a and x->a are different), I would use union: 但是由于您需要以两种不同的方式访问相同的字段(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;

Now x.virtual_a and ya are in the same memory address. 现在x.virtual_a和ya位于相同的内存地址。

And you can rewrite your code as follows: 您可以按以下方式重写代码:

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

The only clumsy part is adding Y inside X. 唯一笨拙的部分是在X内添加Y。

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

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