Могу ли я "расширить" структуру в C?
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo;
int b;
} bar;
По существу я хочу:
bar b;
b.a;
Я знаю, что я мог бы делать b.foo_name.a, если бы я назвал структуру foo в строке, но Id предпочитает не делать.
Как это сделать?
Этот вопрос получил множество разных ответов, поэтому позвольте мне объяснить необходимость. Причина, по которой я хочу сделать это, состоит в том, что у меня есть библиотека, которую мне нужно адаптировать к моей ситуации, а это значит, что я не могу изменить первоначальное объявление структуры. Кроме того, все, что мне нужно сделать, это добавить 1 элемент в начало структуры (почему начало? Потому что у меня есть структура объекта, которая возглавляет все структуры проекта). Я мог бы просто вставить структуру, как вы упоминаете, но ее ДЕЙСТВИТЕЛЬНО раздражает, так как все ссылки должны быть напечатаны "variable- > image.location", что "образ". набрал миллиард типов, это действительно раздражает.
Ответы
Ответ 1
Очевидно, эта функция была добавлена в 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;
}
Ответ 2
Вы можете, используя указатели, потому что указатель на объект структуры гарантированно указывает его первый член. См. в этой статье.
#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;
}
Ответ 3
Невозможно в C
, как вы это делали. Но вы можете имитировать наследование, имеющее переменную-член foo
в bar
.
typedef struct bar_s {
foo obj;
int b;
} bar;
bar b;
b.obj.a = 10;
Ответ 4
Если вы выполняете
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;
}
Ответ 5
Вы можете попробовать использовать наследование:
struct foo_s
{
int a;
};
struct bar_s: foo_a
{
int b;
};
Работает на С++, не уверен, работает ли он на C.
Ответ 6
Это можно легко сделать с помощью препроцессора:
Создайте файл с именем 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;