22
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.

chacham15
  • 13,719
  • 26
  • 104
  • 207
  • Some compilers offer exactly that behavior as an extention. Personally I think it provides too much risk (nesting `struct`s six layers deep and forgetting what names you've used) so I just name the first member `_` - short, consistent, out of the way, and not terribly inconvenient. (The name might actually be reserved by the standard and/or compiler but I doubt anyone would use it if it was.) – Chris Lutz Sep 10 '11 at 08:56
  • If `image` is annoying to type a lot, use `img`. Use find-and-replace to do it for you. Don't worry - whatever you end up having to do, you'll survive. – Chris Lutz Sep 10 '11 at 09:09
  • 1
    @chacham15 Dude, avoid tagging a C question as C++. These two are completely different languages. – amit kumar Sep 10 '11 at 09:21
  • yes, i removed the tag quickly – chacham15 Sep 10 '11 at 10:00
  • You don't need to use `foo_s` for the struct name. `typedef struct foo { ... } foo;` works fine. – 12Me21 Nov 02 '18 at 22:35

8 Answers8

43

Evidently this feature has been added to C11, but alas I don't have access to a C compiler of recent vintage (>= 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;
}
wcochran
  • 10,089
  • 6
  • 61
  • 69
13

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;
}
Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
  • 1
    It's even better when they take `void *` pointers and avoid the caller-side casting. (Some people's values of "better" may be different than mine.) – Chris Lutz Sep 10 '11 at 09:03
  • 2
    Yes, it's certainly more convenient for the caller. I wanted to demonstrate that the author of the foo functions doesn't have to know that the "real" struct is something else than foo. – Jouni K. Seppänen Sep 10 '11 at 09:38
  • 1
    Well, both approaches are right and wrong at the same time. Having to typecast forces client code to be of low quality. This can be solved by using `void *`, however that eliminates type safety which is even worse. Still these are a nice answer and some good arguments, especially Jouni's last comment when it comes to abstractions (the point of inheritance), yet the above factors need to be taken into account. Here's the C11 solution: **http://modelingwithdata.org/arch/00000113.htm**; I wonder if there was a workaround for other versions of C – Powerslave Dec 02 '13 at 17:06
10

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;
Mahesh
  • 34,573
  • 20
  • 89
  • 115
2

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;
kungfooman
  • 4,473
  • 1
  • 44
  • 33
2

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;
 }
Guy L
  • 2,824
  • 2
  • 27
  • 37
  • The question made no mention of wanting run-time "types" like you describe. – Chris Lutz Sep 10 '11 at 08:53
  • @Chris, You might be right, but the "bar.a" looked like a python code to me (where classes can be extended on run-time). So that's what came first to my mind... – Guy L Sep 10 '11 at 08:56
  • It looked more like plain old C++ inheritance to me, and his code is valid formcertain compilers with extensions enabled. And there would be no problem with `sizeof(bar)` unless `foo` was an incomplete type. @pst - Not really. The question is asking "I know I can do X, but Y would be more convenient. Can I do that instead?" Explaining Z isn't really that relevant. – Chris Lutz Sep 10 '11 at 09:00
  • @Chris, As I said before, I might misunderstood the question at first glance. I tried to explain why C does not support incomplete types (the compiler needs the size of an object) – Guy L Sep 10 '11 at 09:21
1

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.

Abraham Le
  • 114
  • 3
0

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
s30904
  • 1
  • 1
0

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.

neodelphi
  • 2,706
  • 1
  • 15
  • 22