Why does declaring a structure within a structure not work? - c

Learning C recently and came across this problem
struct myStruct {
int a;
float b;
struct thisStruct c;
};
struct thisstruct {
int d;
float e;
struct myStruct c;
};
'struct thisStruct c;' returns an error, but not 'struct myStruct c;'. Why is this so?

For starters there is a typo in the presented code snippet.
struct myStruct {
int a;
float b;
struct thisStruct c;
};
struct thisstruct {
int d;
float e;
struct myStruct c;
};
It seems you mean that the second declaration declares a structure with the name thisStruct instead of the name thisstruct.
As for your question then according to the C Standard (6.7.2.1 Structure and union specifiers)
3 A structure or union shall not contain a member with incomplete or
function type (hence, a structure shall not contain an instance of
itself, but may contain a pointer to an instance of itself), except
that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union
containing, possibly recursively, a member that is such a structure)
shall not be a member of a structure or an element of an array
In this structure declaration
struct myStruct {
int a;
float b;
struct thisStruct c;
};
the type struct thisStruct is an incomplete type. Its size is unknown. You may declare a pointer of this structure type like
struct myStruct {
int a;
float b;
struct thisStruct *c;
};
because pointer types are always complete types. Their sizes are known.
Otherwise in these declarations
struct myStruct {
int a;
float b;
struct thisStruct c;
};
struct thisStruct {
int d;
float e;
struct myStruct c;
};
you have an infinite recursion. That is the definition of the data member
struct thisStruct c;
includes the definition of the structure thisStruct that in turn again includes the definition of the structure myStruct and so on.

This C code too, like every other C code, can be regarded as parsed from top to bottom. Therefore at the point where you declare struct thisStruct c, the compiler has no idea what that type is, because it has not yet seen that struct definition.
You could declare pointers to structs before the compiler knows what those structs are, by forward declaring the struct:
struct thisStruct;
struct myStruct {
int a;
float b;
struct thisStruct* c;
};
However, this means you have to use pointers.
That being said, a program design of some X containing an Y containing an X is very likely nonsense. I very much doubt there exists a valid scenario where you would need that. Reconsider your design.

As the C compiler does not know the size of the struct or union which was not yet declared it cant place such a struct or union inside other data structure. Only pointer (as size of pointer is known to the compiler) to not yet declared structure or union can be used.

Related

Why are pointers to incomplete types allowed and not variables of incomplete types?

Why is the following legal:
typedef struct a aType;
struct a
{
int x;
aType *b;
};
and the following illegal:
void main()
{
typedef struct a aType;
aType someVariable;
struct a
{
int x;
aType *b;
};
}
I'm just curious as in each case it is forward referencing and as far as I know, at least for functions and variables, forward referencing is not legal.
Also, would the answer for this be the same for C++ as well?
You are allowed to create pointers to incomplete types, because the size of the pointer object does not depend on the size of the pointed-to type. Pointers to different struct types have the same size and representation, regardless of the size of the struct type itself.
You are not allowed to create instances of incomplete types, since the size of the type isn't known.
This of it this way:
typedef struct a aType;
struct a { int x; aType *b; };
is the same as:
struct a;
typedef struct a aType;
struct a { int x; aType *b; };
So you're forward-declaring a struct, typedefing it and later defining it. Perfectly fine.
Now the second example:
typedef struct a aType;
aType someVariable;
struct a { int x; aType *b; };
This has nothing to do with the fact that it's in local scope.
What's happening is this:
struct a;
typedef struct a aType;
aType someVariable; // error: when it gets here, aType is still incomplete
struct a { int x; aType *b; };
aType someVariable; // perfectly fine, aType not incomplete
Remember that compilation happens in order. When you try to declare someVariable the compiler doesn't know what struct a is yet, so it doesn't know its size, hence it doesn't know how much memory to allocate for it, hence a compile error. Declaring it after aType is defined works as expected.

Understanding C syntax for function pointers

Below code is to implement vtable.
In the below code,
struct A;
typedef struct {
void (*A)(struct A*);
void (*update)(struct A*);
int (*access)(struct A*);
} A_functable;
typedef struct A{
int a;
A_functable *vmt;
} A;
I could not understand mentioning (*A) as function pointer in void (*A)(struct A*); that is member in A_functable, where A is
typedef struct A{
int a;
A_functable *vmt;
} A;
How to understand this syntax?
In
void (*A)(struct A*);
, the first A does not refer to typedef struct A { ... } A as that is only defined further below. At this point the compiler doesn't know anything about a type called A. A is simply the name of the struct member, just like update and access.
(struct A does refer to the struct, however: There's a struct A; declaration further up.)
They are in different namespaces.
In C there are four different namespaces
Tags for a struct/union/enum
Members of struct/union (actually a separate namespace is assigned to each struct/union)
Labels
Ordinary identifiers.
(Section 6.1.2.3 of C90)
Identifiers in different namespaces will not clash with one other and will be referred as separate entities.
So, in your case,
The member of the structure, (*A) being a function pointer is in the second namespace.
The tags for the struct typedef struct A is in the first namespace,
The struct type being an ordinary identifier is in the fourth namespace.
Additionally, the function type for the function pointer (*A)(struct A*) is in the fourth namespace, being an ordinary type.

Is a struct {...}; a type or an unnamed variable?

Is the following, at file scope, a type declaration or an unnamed variable?
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
If it is a type definition, then what is the difference with:
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
?
(Background: see my answer at Changing a variable from global to local - C, where I believe the first introduces an unnamed variable that is then optimized away by the compiler.)
Note: the question has been flagged as a possible duplicate of In what scope is a struct member identifier put? but I believe I am not asking a question about the scope of the members but about what the declarations actually create. However. answers to Difference between 'struct' and 'typedef struct' in C++? do explain my question.
As per the C standard, a structure declaration in the form like
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
is the declaration of a type. Quoting C11, chapter ยง6.7.2.1
The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union. [...]
C standard does not mandate creating a variable (either named or unnamed) for that type.
In your second snippet, you actually (try to) typedef to nothing. However, if you change your snippet to the form of
typedef struct {
//.....members
} student_s ;
you'll be creating a type student_s (typedef to an unnamed structure type) which you can use later.
FWIW, we never talked about a variable being created here, anyways. It's all about types.
First declaration declares a type. After that declaration, the type struct student_s is known, and you can declare variables of that type or pointer to it :
struct student_s student1;
struct student_s *pStudent;
The second declaration is weird even if is compiles. The common usage would be :
typedef struct {
char* name;
int age;
double height;
struct student_s* next;
} studend_t;
which declares an alias student_t to an anonymous struct. It can then be used directly :
student_t student1;
student_t *pStudent;
BUT THE SECOND EXAMPLE DOES COMPILE (even with a warning) AND IS THE SAME AS FIRST ONE !
What it really does is to declare a void alias to struct student_s. The typedef is ignored and produces a warning : typedef requires a name, but as a side effect, the struct is declared, exactly as it was in first example.
So the true answer to the actual question is THERE ARE NO DIFFERENCES except for a warning.
Both are type definitions. The second one is one incomplete. It doesn't supply a name as the the argument of typedef. Much better is to use
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
} student;
Regarding the legality of
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
I've asked that as a separate question, Legality of `typedef struct foo {int bar};`
It's a type, and you can't have an anonymous instance of a struct. For comparison, this declares both the type struct_type and an instance struct_instance of that type:
struct struct_type {
/* blah */
} struct_instance;
If you wanted to declare another instance in isolation (from the type decl) you'd use
struct struct_type another_instance;
The use of typedef - if done correctly, unlike your example - just allows you to give the type another name which doesn't require the struct keyword to declare an instance:
typedef struct_type MyStruct;
MyStruct yet_another_instance;
or equivalently
typedef struct struct_type {
/* blah */
} MyStruct;
omitting the name (struct_type) gives you an anonymous struct type which can only referred to by its typedef'd name.
Note 1
Since your original struct contains a next pointer to its own type, that type must have a name at the point the member is declared. So, you cannot declare an anonymous struct with a self-typed pointer. If you give your anonymous struct type a name with typedef, that name doesn't exist until after the member declaration, so can't be used there.
typedef struct /*S*/ {
struct S *next; /* T doesn't exist yet, so without S, you can't declare this */
} T;
Note 2
You can declare an anonymous instance of an anonymous union, as a member:
struct S {
union {
int i;
unsigned u;
};
};
struct S s;
s.i = -1;
printf("%x\n", s.u);
but that's a very special case. I took the remark about this out of the main argument, in case it was misleading.
struct A { ... }
creates struct 'A' visible in struct namespace (which has nothing common with C++ namespaces). So, to access struct you have to use struct keyword;
struct A a;
When defined with typedef struct
typedef struct A { ... } B;
becomes visible and bound to B, and you can easily create struct like common variable of type B
B a;
Please, correct me someone, if I am wrong.
The difference is that with the first example, you have to declare a new variable like this: struct student_s variable;, however with the second example, you may simply do student_s variable;.

What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?

I am a beginner in C programming and I know the difference between struct type declaration and typedef struct declaration. I came across to know an answer saying that if we define a struct like:
typedef struct {
some members;
} struct_name;
Then it will be like providing an alias to an anonymous struct (as it is not having a tag name). So it can't be used for forward declaration. I don't know what the forward declaration means.
Also, I wanted to know that for the following code:
typedef struct NAME {
some members;
} struct_alias;
Is there any difference between NAME and struct_alias? Or are both equal as
struct_alias is an alias of struct NAME ?
Furthermore, can we declare a variable of type struct NAME like these:
struct_alias variable1;
and/or like:
struct NAME variable2;
or like:
NAME variable3;
struct forward declarations can be useful when you need to have looping struct declarations. Example:
struct a {
struct b * b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
When struct a is declared it doesn't know the specs of struct b yet, but you can forward reference it.
When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef.
This is illegal:
struct a {
b * b_pointer;
int c;
};
typedef struct {
struct a * a_pointer;
void * d;
} b;
// struct b was never declared or defined
This though is legal:
struct a {
struct b * b_pointer;
int c;
};
typedef struct b {
struct a * a_pointer;
void * d;
} b;
// struct b is defined and has an alias type called b
So is this:
typedef struct b b;
// the type b referes to a yet undefined type struct b
struct a {
b * struct_b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
And this (only in C, illegal in C++):
typedef int b;
struct a {
struct b * struct_b_pointer;
b b_integer_type;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
// struct b and b are two different types all together. Note: this is not allowed in C++
Forward declaration is a promise to define something that you make to a compiler at the point where the definition cannot be made. The compiler can use your word to interpret other declarations that it would not be able to interpret otherwise.
A common example is a struct designed to be a node in a linked list: you need to put a pointer to a node into the struct, but the compiler would not let you do it without either a forward declaration or a tag:
// Forward declaration
struct element;
typedef struct {
int value;
// Use of the forward declaration
struct element *next;
} element; // Complete definition
and so it cant be used for forward declaration
I think that author's point was that giving your struct a tag would be equivalent to a forward declaration:
typedef struct element {
int value;
// No need for a forward declaration here
struct element *next;
} element;
Forward declaration is a declaration preceeding an actual definition, usually for the purpose of being able to reference the declared type when the definition is not available. Of course, not everything may be done with the declared-not-defined structure, but in certain context it is possible to use it. Such type is called incomplete, and there are a number of restrictions on its usage. For example:
struct X; // forward declaration
void f(struct X*) { } // usage of the declared, undefined structure
// void f(struct X) { } // ILLEGAL
// struct X x; // ILLEGAL
// int n =sizeof(struct X); // ILLEGAL
// later, or somewhere else altogether
struct X { /* ... */ };
This can be useful e.g. to break circular dependencies, or cut down the compilation time, as the definitions are usually significantly larger, and so more resources are required to parse it.
In your example, struct NAME and struct_alias are indeed equivalent.
struct_alias variable1;
struct NAME variable2;
are correct;
NAME variable3;
is not, as in C the struct keyword is required.
struct_alias and struct NAME are same ,struct_alias is an alias to struct NAME
These both are same and allowed
struct_alias variable1;
struct NAME variable1;
this is illegal
NAME variable3;
See this article on Forward declaration
As others stated before, a forward declaration in C/C++ is the declaration of something with the actual definition unavailable. Its a declaration telling the compiler "there is a data type ABC".
Lets pretend this is a header for some key/value store my_dict.h :
...
struct my_dict_t;
struct my_dict_t* create();
char* get_value(const struct my_dict_t* dict, const char* name);
char* insert(struct my_dict_t* dict, const char* name, char* value);
void destroy(struct my_dict_t* dict);
...
You dont know anything about my_dict_t, but actually, for using the store
you dont need to know:
#include "my_dict.h"
...
struct my_dict_t* dict = create();
if(0 != insert(dict, "AnEntry", strdup("AValue"))) {
...
}
...
The reason for this is: You are only using POINTERS to the data structure.
POINTERS are just numbers, and for dealing with them you dont need to know what they are pointing at.
This will only matter if you try to actually access them, like
struct my_dict_t* dict = create();
printf("%s\n", dict->value); /* Impossible if only a forward decl is available */
So, for implementing the functions, you require an actual definition of my_struct_t.
You might do this in the source file my_dict.c like so:
#include "my_dict.h"
struct my_dict_t {
char* value;
const char* name;
struct my_dict_t* next;
}
struct my_dict_t* create() {
return calloc(1, sizeof(struct my_dict_t));
}
This is handy for several situations, like
For resolving circular type dependencies, like Sergei L. explained.
For encapsulation, like in the example above.
So the question that remains is: Why cant we just omit the forward declaration at all when using the functions above? In the end, it would suffice for the compiler to know that all dict are pointers.
However, the compiler does perform type checks:
It needs to verify that you don't do something like
...
int i = 12;
char* value = get_value(&i, "MyName");
...
It does not need to know how my_dict_t looks like, but it needs to know that &i is not the type of pointer get_value() expects.

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