Having a struct -
typedef struct Point{
....
}
I want to write its prototype before the main() , something like -
typedef struct Point ;
int main() {
Point p1 ,p2 ;
...
}
typedef struct Point {
int x;
int y;
} Point;
The above gives me error - unknown type name 'Point' .
How could I achieve that right ?
Edit:
I know that it would be work if I define to struct before the main() . I just want to know whether it have any prototye similarly to function prototye.
You cannot do this, because the C language is organized around one pass compilation. At the point where a type name is used to declare or define something, that type have been previously declared.
There is a relaxation of this rule, namely: you can define incomplete types in C. However, incomplete types cannot be used to define objects: at least, not certain kinds of objects. So this is invalid:
struct foo; /* introduces incomplete type foo */
struct foo x; /* incomplete type for external definition is okay, as long
as the type is completed before the end of the translation unit. */
extern struct foo e; /* incomplete type for external declaration is allowed even if
the type is not completely known in this translation unit
at all. A definition of the object e must exist somewhere
in the linked program---unless e is not used; then a definition
need not exist at all. */
void func(void)
{
struct foo y; /* incomplete type not okay here */
}
struct bar {
struct foo z; /* not okay here */
};
struct foo {
char *s;
}; /* struct foo is now a complete type, but it's too late in the file */
The last declaration above, which completes the type struct foo allows for the struct foo x; definition to be valid. So there is some "lexically retroactive" action in the C type system; it's just not general.
The situations marked as "not okay" require the struct type to be complete at that point in the source code.
If you want to define local variables of type Point in your main function, that type must be declared and complete prior to that function. If that type is not complete, you can still define variables of type Point *: pointer to Point. But these pointers cannot be dereferenced.
This declaration:
typedef struct Point;
is not valid in C.
How could I achieve that right ?
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
}
You cannot achieve the same with struct Point declaration after main because the implementation has to know the storage of Point objects p1 and p2 when you declare them in main.
You won't be able to do that because the compiler would need to know how much space to allocate for Point when you allocate it. Prototyping wouldn't give you this information.
You could do this, as the size of the pointer will be known:
typedef struct Point Point;
int main() {
Point * p1;
}
struct Point {
int x;
int y;
};
I don't know if that will meet your needs, though
The problem is that you are declaring your struct after main.
typedef struct Point ; // you dont really need this.
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
even better is this:
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
Put the declaration in another file (e.g., Point.h) that gets included at the top of your main() file, and put the definition in a separately-compiled implementation file (e.g., Point.cpp).
Related
This doesn't work for foo
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *); // unknown type name ‘Foo’
void bar (Bar *);
typedef struct
{
int y;
}
Foo;
This doesn't work for bar
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (struct Foo *);
void bar (struct Bar *); ‘struct Bar’ declared inside parameter list
typedef struct
{
int y;
}
Foo;
Some of my structs have to be forward-declared, because they are passed as pointers, and some of them have to be not forward-declared, because they are passes as values.
Is there a way to declare types in C such that all function prototypes can consistently always refer to custom types in the same way, regardless of whether they are forward-declared or not?
Your problem is not forward-declared vs. non-forward-declared, it's struct X vs. typedef struct { ... } X.
You can solve this by using struct X only:
struct Foo;
struct Bar
{
int x;
};
void foo (struct Foo *);
void bar (struct Bar *);
struct Foo
{
int y;
};
Once you have that, you can introduce typedef names:
typedef struct Foo Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *);
void bar (Bar *);
struct Foo
{
int y;
};
You can't pre-declare typedefs, so we still need a real struct type we can forward to. There's a small inconsistency here: Foo is the same as struct Foo, but there is no struct Bar, only Bar. You can fix that by switching to
typedef struct Bar
{
int x;
}
Bar;
This defines struct Bar and Bar simultaneously.
struct Foo;
Declare a structure named Foo. But, you must declare a typedef Foo of structure named Foo.
#include <stdio.h>
typedef struct Foo Foo;
typedef struct {
int x;
} Bar;
void foo(Foo *);
void bar(Bar *);
struct Foo {
int y;
};
int main(void) {
printf("Hello, world!\n");
}
The first order of business is to point out that in your examples there is no struct Foo. There is only a struct without a tag that you typedef as Foo.1
Is there a way to declare types in C such that all function prototypes can consistently always refer to custom types in the same way, regardless of whether they are forward-declared or not?
The definition or declaration of the struct should appear before the struct is used in a function parameter list. Otherwise the declarations scope is only the function prototype, which is almost certainly not what you want.
The way to achieve what you want is only through disciplined coding.
A forward declaration is all you ever really need for a function prototype. You don't need the full struct definition until the function itself is defined or called.
struct Foo;
void foo (struct Foo); // Okay, only at the call site or definition site
// do we need the full struct definition.
A short example to demonstrate
#include <stdio.h>
struct Foo;
void foo (struct Foo);
struct Foo
{
int y;
};
int main(void) {
struct Foo f = { .y = 1 };
foo(f);
return 0;
}
void foo (struct Foo f)
{
printf("%d", f.y);
}
It's much clearer that it's okay when the definitions and declarations are spread out among different translation units, but the above will have to do.
So what I suggest to you, is that you always forward declare your structs on a separate line, before they are to be used in function prototypes (by pointer or by value). And refrain from introducing the full definition until it's really needed.
1 A lovely correspondence on fa.linux.kernel where Linus Torvalds articulates far better than me why you should prefer to use the full struct tag.
The only "forward declaration" and reference supported by C is the pointer, e.g.:
void myFunc (struct XYZ *p);
This tells the compiler you are referring to a type struct XYZ, possibly not yet declared, of which you are passing a pointer. This allows the compiler to perform type checking without knowing what this structure actually consists of.
Note that pointers are all the same size, so there is no check on the pointer itself, just on the thing it is pointing to.
See also other solutions that explain using typedef.
You mix up forward declaration and type definitions. Both are different things. If you want to have the same kind of usage of forward declared structs do it:
struct Foo; // forward declaration
struct Bar { int x; }; // definition
void foo(struct Foo); // works for a prototype
void bar(struct Bar); // works for a prototype
You cannot forward declare type definitions. Maybe this is the reason for the name definition. However, you can type define a forward declaration:
struct Foo; // forward declaration
typedef struct Foo Foo_t; // type definition of a forward declaration
struct Bar { int x; }; // definition
typedef struct Bar Bar_t; // type definition of a definition
void foo(Foo_t); // works
void bar(Bar_t); // works
If you have a function definition the type has to be completed. This means that you have already defined the forward declared type at this location or that you have to use pointers. Again: It does not matter, whether you use structures or type definitions.
BTW: As you can see in my examples, it is an urban legend that incomplete structure types has to be passed "by reference". You can use the incomplete type in the function declaration (prototype). However, when you define the function, the type has to be completed. This is no deal in most cases.
I wrote a small code in C in which two struct types were defined which have members of each other in their definition. Case 1: If the struct foo is defined before struct bar, the code is compiled as expected. Case 2: If struct foo is defined after struct bar it will not compile which is also expected as there is no way to know the memory requirement of a struct foo variable. But I was expecting it will compile if a forward declaration of struct foo is used in case 2. But it does not work. What am I missing?
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
forward declaration only informs the compiler that there is something that is called foo it does nothing says about size.
you can use foo* since this is a pointer of known size but not foo itself because the size is unknwon, so the compiler does not know how the memory layout of barshould look like.
And the compiler only do a single pass through your document. so it cannot know the strucutre that is defined ahead.
If a struct type X appears only as a pointer type in a structure declaration or its functions, and the code in the header file does not attempt to access any member variables of X, then you should not #include X.h, but instead make an incomplete declaration of X (also called a
"forward" declaration) before the first use of X. Here is an example in which a structure type Thing refers to X by a pointer:
struct X; /* incomplete ("forward") declaration */
struct Thing {
int i;
struct X* x_ptr;
};
The compiler will be happy to accept code containing pointers to an incompletely known structure type, basically because pointers always have the same size and characteristics regardless of what they are pointing to. Typically, only the code in the .c file needs to access the members (or size) of X, so the .c file will #include "X.h". This is a powerful technique for encapsulating a module and decoupling it from other modules.
That is, it would work correctly if your code was something like :
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo *ch; /* MODIFIED LINE */
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
But in your case, struct bar is having an "element" of type struct foo. Hence it will give error field has incomplete type.
Also for your information, see the below snippet (will work perfectly):
#include<stdio.h>
#include<stdlib.h>
struct bar
{
int a;
struct aabar *next; /* MODIFIED LINE - aabar never declared */
struct foo *ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
A declaration also can't let the compiler know how to allocate the memory.
In your struct foo the element nx is a pointer, so defining struct foo doesn't require memery size. However, on struct bar the element ch is not a pointer, so the defining struct bar needs to know the size of struct foo. The forward declaration doesn't specify the memory size, the definition does.
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.
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;
What is forward reference in C with respect to pointers?
Can I get an example?
See this page on forward references. I don't see how forward referencing would be different with pointers and with other PoD types.
Note that you can forward declare types, and declare variables which are pointers to that type:
struct MyStruct;
struct MyStruct *ptr;
struct MyStruct var; // ILLEGAL
ptr->member; // ILLEGAL
struct MyStruct {
// ...
};
// Or:
typedef struct MyStruct MyStruct;
MyStruct *ptr;
MyStruct var; // ILLEGAL
ptr->member; // ILLEGAL
struct MyStruct {
// ...
};
I think this is what you're asking for when dealing with pointers and forward declaration.
I think "forward reference" with respect to pointers means something like this:
struct MyStruct *ptr; // this is a forward reference.
struct MyStruct
{
struct MyStruct *next; // another forward reference - this is much more useful
// some data members
};
The pointer is declared before the structure it points to is defined.
The compiler can get away with this because the pointer stores an address, and you don't need to know what is at that address to reserve the memory for the pointer.
Forward reference is when you declare a type but do not define it.
It allows you to use the type by pointer (or reference for C++) but you cannot declare a variable.
This is a way to say to the compiler that something exists
Say that you have a Plop structure defined in Plop.h:
struct Plop
{
int n;
float f;
};
Now you want to add some utility functions that works with that struct. You create another file PlopUtils.h (let's say you can't change Plop.h):
struct Plop; // Instead of including Plop.h, just use a forward declaration to speed up compile time
void doSomething(Plop* plop);
void doNothing(Plop* plop);
Now when you implement those function, you will need the structure definition, so you need to include the Plop.h file in your PlopUtils.cpp:
#include "PlopUtils.h"
#include "Plop.h" // now we need to include the header in order to work with the type
void doSomething(Plop* plop)
{
plop->n ...
}
void doNothing(Plop* plop);
{
plop->f ...
}
I think the C compiler originally had a pass in which it did symbol table building and semantic analysis together. So for example:
....
... foo(a,b) + 1 ... // assumes foo returns int
....
double foo(double x, double y){ ... } // violates earlier assumption
to prevent this, you say:
double foo(double x, double y); // this is the forward declaration
....
... foo(a,b) + 1 ... // correct assumptions made
....
double foo(double x, double y){ ... } // this is the real declaration
Pascal had the same concept.
Adding to previous answers. The typical situation in which forward reference is mandatory is when a struct foo contains a pointer to a struct bar, and bar contains a pointer to foo (a circular dependency between declarations). The only way to express this situation in C is to use a forward declaration, i.e.:
struct foo;
struct bar
{
struct foo *f;
};
struct foo
{
struct bar *b;
};
Forward references allow C compiler to do less passes and significantly reduces compilation time. It is probably was important some 20 years ago when computers was much slower and compliers less efficient.