Могу ли я «расширить» структуру в C? - PullRequest
14 голосов
/ 10 сентября 2011
typedef struct foo_s {
    int a;
} foo;

typedef struct bar_s {
    foo;
    int b;
} bar;

По сути, я хочу сделать:

bar b;
b.a;

Я знаю, что мог бы сделать b.foo_name.a, если бы я назвал структуру foo в баре, но я бы предпочел не делать этого.

Есть ли способ сделать это?

Этот вопрос получил множество разных ответов, поэтому позвольте мне объяснить необходимость.Причина, по которой я хочу это сделать, заключается в том, что у меня есть библиотека, которую мне нужно адаптировать к моей ситуации, а это означает, что я не могу изменить исходное структурирование.Кроме того, все, что мне нужно сделать, это добавить 1 элемент в начало структуры (почему начало? Потому что у меня есть структура 'object', которая возглавляет все структуры в проекте).Я мог бы просто встроить структуру, как вы упомянули, но она ДЕЙСТВИТЕЛЬНО раздражает, так как все ссылки должны быть напечатаны 'variable-> image.location', что 'image'.набранный миллиард типов действительно раздражает.

Ответы [ 6 ]

26 голосов
/ 25 января 2013

Очевидно эта функция была добавлена ​​в C11 , но, увы, у меня нет доступа к компилятору C недавнего сбора винограда (> = GCC 4.6.2).

typedef struct foo {
  int a;
} foo;

typedef struct bar {
  struct foo;
  int b;
} bar;

int main() {
  bar b;
  b.a = 42;
  b.b = 99;
  return 0;
}
10 голосов
/ 10 сентября 2011

Вы можете, используя указатели, потому что указатель на объект структуры гарантированно указывает на его первый член.См. Например эту статью .

#include <stdlib.h>
#include <stdio.h>

typedef struct foo_s {
    int a;
} foo;

typedef struct bar_s {
    foo super;
    int b;
} bar;

int fooGetA(foo *x) {
  return x->a;
}

void fooSetA(foo *x, int a) {
  x->a = a;
}

int main() {
  bar* derived = (bar*) calloc(1, sizeof(bar));
  fooSetA((foo*) derived, 5);
  derived->b = 3;
  printf("result: %d\n", fooGetA((foo*) derived));
  return 0;
}
7 голосов
/ 10 сентября 2011

Невозможно в C, как вы это сделали. Но вы можете имитировать наследование, используя переменную-член foo в bar.

typedef struct bar_s {
    foo obj;
    int b;
} bar;

bar b;
b.obj.a = 10;
2 голосов
/ 10 сентября 2011

Если вы можете

typedef struct foo_s {
    int a;
  } foo;

typedef struct bar_s {
 foo my_foo;
int b;
} bar;

, чтобы вы могли сделать:

bar b; b.my_foo.a = 3;

В противном случае, это невозможно сделать в C, поскольку sizeof(bar_s) наносит ущерб во время компиляции.Это не очень хорошая практика, но вы можете сохранить указатель void * ptr; в bar_s и другое перечисление, которое описывает тип ptr, и приведено к типу.

т.е.:

typedef enum internalType{
  INTERNAL_TYPE_FOO = 0,
}internalType_t;

typedef struct bar_s {
 internalType_t ptrType;
 void* ptr;
int b;
} bar;

а затем:

bar b;  foo f;
b.ptrType = INTERNAL_TYPE_FOO;
b.ptr = &f;

и еще где-то в коде:

 if (b.ptrType == INTERNAL_TYPE_FOO) {
    foo* myFooPtr = (foo *)b.ptr;
 }
0 голосов
/ 13 декабря 2016

Это легко сделать с помощью препроцессора:

Создать файл с именем base_foo.h:

int foo;

Тогда просто включите его:

typedef struct foo_s {
    #include "base_foo.h"
} foo;

typedef struct bar_s {
    #include "base_foo.h"
    int b;
} bar;
0 голосов
/ 10 сентября 2011

Вы можете попробовать использовать наследование:

struct foo_s
{
    int a;
};

struct bar_s: foo_a
{
    int b;
};

Работает в C ++, не уверен, работает ли он в C.

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