'Can I 'extend' a struct in C?
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo;
int b;
} bar;
Essentially I want to do:
bar b;
b.a;
I know that i could do b.foo_name.a if I had named the foo struct in bar, but Id prefer not to.
Any way to do this?
This question has gotten a variety of different answers, so let me explain the need. The reason I want to do this is because I have a library which I need to adapt to my situation, meaning that I cant modify the original struct decleration. Furthermore, all I need to do is add 1 item to the beginning of the struct (why the beginning? because I have an 'object' struct which heads all the structs in the project). I could simply embed the struct like you mention but its REALLY annoying as all references will need to be typed 'variable->image.location' that 'image.' typed a billion types is really annoying.
Solution 1:[1]
You can, using pointers, because a pointer to a structure object is guaranteed to point its first member. See e.g. this article.
#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;
}
Solution 2:[2]
Not possible in C the way you did. But you can mimic inheritance having a foo member variable in bar.
typedef struct bar_s {
foo obj;
int b;
} bar;
bar b;
b.obj.a = 10;
Solution 3:[3]
If you ment
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo my_foo;
int b;
} bar;
so you can do:
bar b; b.my_foo.a = 3;
Otherwise, There's no way of doing it in C since the sizeof(bar_s) is detriment on compile time. It's not a good practice but you can save a void * ptr; pointer within bar_s, and another enum which describes the ptr type, and cast by the type.
i.e:
typedef enum internalType{
INTERNAL_TYPE_FOO = 0,
}internalType_t;
typedef struct bar_s {
internalType_t ptrType;
void* ptr;
int b;
} bar;
and then:
bar b; foo f;
b.ptrType = INTERNAL_TYPE_FOO;
b.ptr = &f;
and some where else in the code:
if (b.ptrType == INTERNAL_TYPE_FOO) {
foo* myFooPtr = (foo *)b.ptr;
}
Solution 4:[4]
It can be easily done via preprocessor:
Create a file named base_foo.h:
int foo;
Then simply include it:
typedef struct foo_s {
#include "base_foo.h"
} foo;
typedef struct bar_s {
#include "base_foo.h"
int b;
} bar;
Solution 5:[5]
There is a confusion between anonymous structures and unions with nameless field. The nameless field is a Microsoft Extension.
struct known {
struct /* anonymous */ {
int anonymous;
};
int known;
};
An anonymous struct or union is a struct or union without any tag name that is embedded within another struct or union. It does not need to have any field names either.
A nameless field is a Microsoft Extension that allows limited inheritance in C.
struct A {
int a;
};
struct B {
struct A: // nameless field
int b;
};
Anonymous struct or union are not Nameless Fields, and Nameless Fields are not Anonymous, at least the way C11 standard defines it.
Solution 6:[6]
You can try using inheritance:
struct foo_s
{
int a;
};
struct bar_s: foo_a
{
int b;
};
Works in C++, not sure if it works in C.
Solution 7:[7]
This is the simplest way without the c flags
#include <stdio.h>
#define foo_s struct { int a; }
typedef foo_s foo;
typedef struct bar_s {
foo_s; // extends foo_s
int b;
} bar;
int main(void)
{
bar b = {
.a = 1,
.b = 2,
};
foo *f = (foo *)&b;
printf("a: %d\n", f->a);
return 0;
}
$ gcc inherit.c
$ ./a.out
a: 1
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jouni K. Seppänen |
| Solution 2 | Mahesh |
| Solution 3 | |
| Solution 4 | kungfooman |
| Solution 5 | Abraham Le |
| Solution 6 | neodelphi |
| Solution 7 |
