Приведение структур в C, когда первые поля не выровнены - PullRequest
0 голосов
/ 01 апреля 2012

Учитывая две структуры в 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: Можно ли это сказать?

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 ]

2 голосов
/ 01 апреля 2012

Нет, ваша функция 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 (хотя может быть исключение для меток с одинаковой структурой с разными метками, как описано Хьюбертом).

Я подозреваю, что лучшим решением проблемы, о которой вы спрашивали, является использование union, которое часто можно использовать для выполнения ваших задач.Но, строго говоря, если у вас есть объект u типа union и вы установили u.a, доступ к значению u.b до установки u.b имеет неопределенное поведение.Хотя обычно люди не беспокоятся об этом.

1 голос
/ 01 апреля 2012

Это должно работать.Но так как вам нужно получить доступ к одним и тем же полям двумя разными способами (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 и ya находятся втот же адрес памяти.

И вы можете переписать свой код следующим образом:

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

Единственная неуклюжая часть - это добавление Y внутри X.

1 голос
/ 01 апреля 2012

если обе структуры имеют одинаковую структуру, это нормально.Имена полей внутри распорок не обязательно должны быть одинаковыми, но их типы должны быть одинаковыми.Каждое подполе в X должно соответствовать подполю в Y по своему типу и положению.Имена полей могут быть разными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...