Structs that refer to each other - c

I want to have two structs that can contain each other. Here is an example:
struct a {
struct b bb;
};
struct b {
struct a aa;
};
But this code doesn't compile. gcc says:
test.c:3: error: field ‘bb’ has incomplete type
Is there a way to achieve this?

How is that supposed to work? a would contain b, which would contain a, which would contain b, etc...
I suppose you want to use a pointer instead?
struct b;
struct a {
struct b *bb;
};
struct b {
struct a *aa;
};
Even that though is bad coding style - circular dependencies should be avoided if possible.

struct a;
struct b;
struct a{
struct b *bb;
};
struct b{
struct a *aa;
};
Most of the header file declare the structure before defining its members. Structure definition will be defined in somewhere else.

The usual way of dealing with this is to make them pointers and then dynamically allocate them or even just assign the pointer from the address of a static instance of the other struct.
struct a {
struct b *bb;
};
struct b {
struct a *aa;
};
struct a a0;
struct b b0;
void f(void) {
a0.bb = &b0;
b0.aa = &a0;
}
I would suggest, however, that you look for a tree-structured organization. Perhaps both objects could point to a common third type.

This is nonsensical.
Imagine if you say that every X contains a Y and every Y contains an X, then inside each X is a Y which in turn contains an X, which in turn contains a Y, which in turn contains an X, ad infinitum.
Instead, you can have an X contain a reference to or (or pointer to) a Y and vice-versa.

Related

Accessing a member in a nested structure

Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
Unlike some variants of BASIC or Pascal that have a with keyword which allows you to access inner members of a structure directly, C has no such construct.
You can do this however with pointers. If you have a particular inner member you're going to access frequently, you can store the address of that member in a pointer and access the member through the pointer.
Suppose for example you had the following data structures:
struct inner2 {
int a;
char b;
float c;
};
struct inner1 {
struct inner2 in2;
int flag;
};
struct outer {
struct inner1 in1;
char *name;
};
And a variable of the outer type:
struct outer out;
Instead of accessing the members of the innermost struct like this:
out.in1.in2.a = 1;
out.in1.in2.b = 'x';
out.in1.in2.c = 3.14;
You declare a pointer of type struct inner2 and give it the address of out.in1.in2. Then you can work directly with that.
struct inner2 *in2ptr = &out.in1.in2;
in2ptr->a = 1;
in2ptr->b = 'x';
in2ptr->c = 3.14;
Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
No. Not via standard C.
To make the accessing code cleaner however, you might consider some static inline helper functions.
For example:
struct snap {
int memb;
};
struct bar {
struct snap sn;
};
struct foo {
struct bar b;
}
static inline int foo_get_memb(const struct foo *f)
{
return f->b.sn.memb;
}
Not completely answering your question.
The 1st member of any struct can be accessed by taking the struct's address, casting it to a pointer type pointing to the struct's 1st member and dereferencing it.
struct Foo
{
int i;
...
};
struct Foo foo = {1};
int i = *((int*) &foo); /* Sets i to 1. */
Adapting this to nested struct's gives us for example:
struct Foo0
{
struct Foo foo;
...
};
struct Foo1
{
struct Foo0 foo0;
...
};
struct Foo2
{
struct Foo1 foo1;
...
};
struct Foo2 foo2;
foo2.foo1.foo0.foo.i = 42;
int i = *((int*) &foo2); /* Initialises i to 42. */
struct Foo0 foo0 = {*((struct Foo*) &foo2)}; /* Initialises foo0 to f002.f001.foo0. */
This is well defined, as the C-Standard guarantees that there is no padding before a struct's 1st member. Still it's not nice.
You could use the -> operator.
You could take the address of an inner member and then access it via the pointer.

How to declare a variable of struct that declared inside another struct?

I have a struct that declared as follow:
struct a {
struct b {
int d;
} c;
};
How to declare a variable of b outside a? In C++ I can use a::b x;. But, in C it required to specifies struct keyword before struct name.
C has a flat layout; when you declare a struct within another struct, the former is just being put into the global namespace.
So, in your example, it is just struct b.
C does not have nested types. You can't write a::x b or anything that ressembles it. If you want to get rid of the struct keyword, that's another problem. Use typedefs. but it won't allow to nest types.
typedef struct b_t {
int d;
} b;
typedef struct {
b c;
} a;
b some_b;
a some_a;
int f() {
some_b.d=42;
some_a.c=some_b;
return 0;
}
.

"Reflection" and incompatible pointer types in C

I'm following a pseudocode snippet in a CompSci paper and trying to implement it in C. In this paper, I have two structs, say A and B. One of them goes something like this:
struct A {
B* next;
int data;
}
while B looks like
struct B {
A* next;
}
Now, for a given instantiation a of A and b of B, at some point the algorithm tells me to do two things:
if a is not B, then do stuff,
a = b
Now, I cannot do reflection in C, and I will obviously get incompatible pointer types for the second requirement. I thought about having a union in the A struct, and perhaps that would help, but I'd like to ask you guys if there's a good design I'm missing.
You are venturing into dangerous territory here. It appears that you are trying to implement polymorphism in a language which has no built in support for it.
There are several schemes you could use which allow you to have an struct A* actually point to memory containing a struct B. A union is probably the least dangerous. But as you point out, there is no reflection. Any pointer only knows that it points to a block of memory, and one way to interpret that block if it is dereferenced. void pointers don't even know that last part. The only way to do type identification is to insert a value identifying the type somewhere in the structure.
Something like this:
struct generic {
enum {ATYPE,BTYPE} type;
union {
struct A a;
struct B b;
};
};
function process(struct generic* a, struct generic* b)
{
if (a.type != BTYPE)
{ //do stuff
}
else
{
*a = *b;
}
}
-edit-
on the other hand, if the content of the structures is as simple as you describe, you could
simply add an isB member to struct a, and only use one type.
I have no idea what this is supposed to do, but here is what you do to make it compile:
struct a a;
struct b b;
typedef struct a
{
struct b* next;
int data;
} A;
typedef struct b
{
A* next;
} B;
int main()
{
A a;
B b;
}
Now, if your struct's are defined in the correct way, then your algorithm should be described that way:
if (a != b->next) then do stuff
a=b->next;
But in this case, the assignment of a=b->next makes only sense if a!=b->next, so it should be moved into the "do stuff"-thing
To make it compilable, you just can add a forward-decl to B in front of the A-definition:
struct B;
struct A {
B* next;
int data;
};
struct B {
A* next;
};
int main () {
A *a=...;
B *b=...;
if (a!=b->next) {
//do stuff
}
a = b->next;
}

copying a struct with a struct member to another struct

is the following code correct?
typedef struct
{
int x;
int y;
} OTHERSTRUCT;
struct DATATYPE
{
char a;
OTHERSTRUCT b;
}
// ...
// now we reserve two structs
struct DATATYPE structA;
struct DATATYPE structB;
// ... probably fill insome values
// now we copy structA to structB
structA = structB;
Are both structs now completely identical? Even the "struct in the struct"?
Thanks!
Yes.
When you assign one struct variable to another, every member is copied one-by-one, including the other struct OTHERSTRUCT you have as a member of DATATYPE.
Yes, their contents is the same afterwards.
There may well be padding bytes between a and b in struct DATATYPE, and these are not guaranteed to be copied by the struct assignment. That doesn't mean that they won't be, just that you can't rely on whether they are or not.
The actual members a and b will have identical values. The effect of the copy applies recursively to members of struct type, so yes the members-of-members are copied too.

What's the syntactically proper way to declare a C struct?

I've seen C structs declared several different ways before. Why is that and what, if anything, does each do different?
For example:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}
Well, the obvious difference is demonstrated in your main:
struct foo a;
bar b;
baz c;
The first declaration is of an un-typedefed struct and needs the struct keyword to use. The second is of a typedefed anonymous struct, and so we use the typedef name. The third combines both the first and the second: your example uses baz (which is conveniently short) but could just as easily use struct _baz to the same effect.
Update: larsmans' answer mentions a more common case where you have to use at least struct x { } to make a linked list. The second case wouldn't be possible here (unless you abandon sanity and use a void * instead) because the struct is anonymous, and the typedef doesn't happen until the struct is defined, giving you no way to make a (type-safe) pointer to the struct type itself. The first version works fine for this use, but the third is generally preferred in my experience. Give him some rep for that.
A more subtle difference is in namespace placement. In C, struct tags are placed in a separate namespace from other names, but typedef names aren't. So the following is legal:
struct test {
// contents
};
struct test *test() {
// contents
}
But the following is not, because it would be ambiguous what the name test is:
typedef struct {
// contents
} test;
test *test() {
// contents
}
typedef makes the name shorter (always a plus), but it puts it in the same namespace as your variables and functions. Usually this isn't an issue, but it is a subtle difference beyond the simple shortening.
It's largely a matter of personal preference. I like to give new types a name starting with a capital letter and omit the struct, so I usually write typedef struct { ... } Foo. That means I cannot then write struct Foo.
The exception is when a struct contains a pointer to its own type, e.g.
typedef struct Node {
// ...
struct Node *next;
} Node;
In this case you need to also declare the struct Node type, since the typedef is not in scope within the struct definition. Note that both names may be the same (I'm not sure where the underscore convention originated, but I guess older C compilers couldn't handle typedef struct X X;).
All your uses are syntactically correct. I prefer the following usage
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Observe that this easily allows to use the typedef already inside the declaration of the struct itself, and that even for struct that reference each other mutually.
The confusion comes about because some of the declarations are in fact declaring up to three C constructs. You need to keep in mind the difference between:
A typedef declaration,
A struct definition, and
A struct declaration.
They are all very different C constructs. They all do different things; but you can combine them into the one compound construct, if you want to.
Let's look at each declaration in turn.
struct foo {
short a;
int b;
float c;
};
Here we are using the most basic struct definition syntax. We are defining a C type and give it the name foo in the tag namespace. It can later be used to declare variables of that type using the following syntax:
struct foo myFoo; // Declare a struct variable of type foo.
This next declaration gives the type another name (alias) in the global namespace. Let's break it down into its components using the previous basic declaration.
typedef foo bar; // Declare bar as a variable type, the alias of foo.
bar myBar; // No need for the "struct" keyword
Now just replace "foo" with the the struct's definition and voila!
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
The above syntax is equivalent to the following sequence of declarations.
struct _baz {
short a;
int b;
float c;
}
typedef _baz baz; // Declare baz as an alias for _baz.
baz myBaz; // Is the same as: struct _baz myBaz;

Resources