forward declaration in C? - c

I have this ordered List structure that has a structure that has two members, an array of type Titem and an int counter. Now, this List can take any type and arrange it in ascending order. Suppose, i decided to typedef char Titem, then the array contains characters, if i typedef int Titem, then the array contains integers. Now, I have a structure somewhere with the type Tage;
how do i make the Ordered List identify it. when i did typedef Tage Titem, it complains. Where should I insert it in the OList header file? Or is there a way to do forward declarations like it is done in C++ in C?
#ifndef OLIST_H
#define OLIST_H
/*typedef char Titem; here, i typedef char to Titem, though commented out..
how do i do similar thing for the Tage datatype i have?
*/
#define MAX 10
typedef struct {
int count;
Titem array[MAX]; //Titem is not typedefed yet, so error..
} TOrderedList;
void initialize_list(TOrderedList *list);
int insert_item(TOrderedList *list, Titem item);
int retrieve_ith(const TOrderedList *list, int i, Titem *item);
int number_of_items(const TOrderedList *list);
int list_empty(const TOrderedList *list);
#endif

You cannot use forward declaration here, unless you want to use pointers to Titem, like:
#define MAX 10
typedef struct {
int count;
Titem *array[MAX]; //Titem is not typedefed yet, so error..
} TOrderedList;
Since the compiler needs to know the size of Titem in order to create the TOrderedList struct.
Include the definition of Titem before you use it, I wouldn't count on the order of the include files in other files.

Or is there a way to do forward declarations like it is done in C++ in C?
No, You cannot use Forward declaration here.
Rationale for why Forward declaration will not work:
When you use forward declaration of any type, the compiler does not know the composition of it nor the members inside it, the compiler only knows that the type exists. Thus, it is an Incomplete type for the compiler. With Incomplete types , One cannot create objects of it or do anything which needs the compiler to know the layout of the type or more than the fact that it is just an type. Since pointers to all objects need just the same memory allocation, You can use the forward declaration when just reffering to types as a pointer.
However, here the compiler needs to know the layout and size of the type Titem since it needs to know how much memory to allocate while creating an array, hence forward declaring the type Titem will not work.
Solution:
You need to let the compiler know of the layout of Titem and the way to do that is to include the header defining the type Titem in the source file where you create the array,

As you are creating an array of Titem, the compiler needs the full definition of the type; a forward declaration will not suffice.
So you need to fully define Tage before you create your typedef.

Related

C: Incomplete definition of type struct

this error seems very easy to fix but i've been trying and have no clue.
So i have three files:
symtable.h:
typedef struct symbolTable *SymTable_T;
symtablelist.c:
#include "symtable.h"
struct Node{
char* key;
void* value;
struct Node* next;
};
struct symbolTable{
struct Node* head;
int length;
};
SymTable_T SymTable_new(void){
/* code */
}
And main.c:
#include "symtable.h"
int main(int argc, const char * argv[]) {
// insert code here...
SymTable_T emptyTable = SymTable_new();
emptyTable->length = 3; <------- ERROR
return 0;
}
I'm getting error: Incomplete definition of type "struct symbolTable"
Can anyone please give me a hint?
The reason i declare my struct in my source file is that i will have another implementation for the header file. so is there another way to fix my bug beside moving my struct declaration?
You can't access the members directly with an opaque pointer - if you keep the implementation in a separate source file, you'll have to access all the members via your interface, and not directly mess with the struct.
For instance, add this to symtable.h:
void SymTable_set_length(SymTable_T table, int len);
this to symtablelist.c:
void SymTable_set_length(SymTable_T table, int len)
{
table->length = len;
}
and in main.c change this:
emptyTable->length = 3;
to this:
SymTable_set_length(emptyTable, 3);
although in this specific case passing the length as an argument to SymTable_new() is an obviously superior solution. Even more superior is not letting the user set the length of a linked list data structure at all - the length is the number of items in it, and it is what it is. It would make no sense to, for instance, add three items to the list, and then allow main.c to set the length to 2. symtablelist.c can calculate and store the length privately, and main.c can find out what the length is, but it doesn't make much sense for main.c to be able to set the length directly. Indeed, the whole point of hiding the members of a struct behind an opaque pointer like this is precisely to prevent client code from being able to mess with the data like that and breaking the data structure's invariants in this manner.
If you want to access the members directly in main.c, then you have to have the struct definition visible, there is no alternative. This will mean either putting the struct definition in the header file (recommended) or duplicating it in main.c (highly unrecommended).
In typedef symbolTable *SymTable_T;, you refer to a non-existent type symbolTable. In C (unlike C++) the type is named struct symbolTable. (Note: the question has changed to fix this since answering it.)
There's a second problem. In main.c the code will need to be able to see the definition of struct symbolTable for you to be able to refer to fields of emptyTable. At the moment, the definition is hidden in a .c file... it should be moved to the header.

Why does "struct T* next" compile when T isn't an existing type?

I am using MinGW on Windows. I am building linked list and I am confused with this.
#include <stdio.h>
#include <stdlib.h>
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
int main(void)
{
List item;
List * head;
head = NULL;
return 0;
}
I now that struct can't have struct variable(object, instance of that struct), but can have pointer of that struct type. Didn't know that pointer can be pointer of unexisting type. struct BlaBla * next;(not for linked list, it must be struct Data * next but mean general talking)
Yes, you can, because then the compiler, upon encountering the unknown type name for the first time, assumes that there's somehwere a struct type definition with this name. Then it will forward-declare the struct name for you, let you use it as a pointer, but you can't dereference it nor can you do pointer arithmetic on it (since it's an incomplete type).
The compiler will accept code such as your example:
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
This is okay because the size of pointers is known to the compiler, and the compiler is assuming that the struct will be defined before it is dereferenced.
Because the compiler acts this way, it's possible to do this:
typedef struct Data
{
int x;
int y;
struct Data * next; /* points to itself */
} List;
However, if you were to include the struct inline, like this:
typedef struct Data
{
int x;
int y;
struct BlaBla blaStruct; /* Not a pointer. Won't compile. */
}List;
The compiler can't work out how big struct Data is because it doesn't know how big struct BlaBla is. To get this to compile, you need to include the definition of struct BlaBla.
Note that, as soon as you need to access the members of struct BlaBla, you will need to include the header file that defines it.
It depends on what you mean by "unexisting". If you haven't even declared BlaBla, you'll get an error.
If you've declared it but not yet defined it, that will work fine. You're allowed to have pointers to incomplete types.
In fact, that's the normal way of doing opaque pointers in C.
So, you might think that this is invalid because there's no declaration of struct BlaBla in scope:
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
However, it's actually okay since it's both declaring struct BlaBla and defining next at the same time.
Of course, since definition implies declaration, this is also okay:
struct BlaBla { int xyzzy; };
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
In order to declare a variable or field of a given type, pass one as a parameter, or copy one to another of the same type, the compiler has to know how many bytes the variable or field occupies, what alignment requirements it has (if any), and what other pointer types it's compatible with, but that's all the compiler needs to know about it. In all common dialects of C, a pointer to any structure will always be the same size and require the same alignment, regardless of the size of the structure to which it points or what that structure may contain, and pointers to any structure type are only compatible with other pointers to the same structure type.
Consequently, code which doesn't need to do anything with pointers to a structure except allocate space to hold the pointers themselves [as opposed to the structures at which they point], pass them as parameters, or copy them to other pointers, doesn't need to know anything about the structure type to which they point beyond its unique name. Code which needs to allocate space for a structure (as opposed to a pointer to one) or access any of its members must know more about its type, but code which doesn't do those things doesn't need such information.

"parameter has incomplete type" warning

I have this in a C file:
struct T
{
int foo;
};
the C file has an include to an h file with those lines:
typedef struct T T;
void listInsertFirst(T data, int key, LinkedList* ListToInsertTo);
the function listInsertFirst is the one I'm getting the warning on. How can I fix it?
As we've found out in the comments, the problem was that the definition of struct T occurred after the definition of T in the header. You really have things backwards here. The header should be defining all the types and function prototypes and your C files should be using them.
What you want to be doing instead is change the signature of your insert function to receive a pointer to your data and the size of the data. Then you can allocate some memory for the data, copy it and store it. You don't need a specific type, just declare it a void *.
void listInsertFirst(void *data, size_t data_size, int key, LinkedList* ListToInsertTo);
Then the caller would do something like this:
struct T { int foo; };
struct T x = { ... };
int someKey = ...;
LinkedList *someList = ...;
listInsertFirst(&x, sizeof x, someKey, someList);
When you include the header file, the compiler knows that T is a structure of unknown size and that listInsertFirst wants one as its first argument. But the compiler cannot arrange a call to listInsertFirst as it doesn't know how many bytes to push on the stack for the T data parameter, the size of T is only known inside the file where listInsertFirst is defined.
The best solution would be to change listInsertFirst to take a T* as its first argument so your header file would say this:
extern void listInsertFirst(T *data, int key, LinkedList* ListToInsertTo);
Then you get an opaque pointer for your T data type and, since all pointers are the same size (in the modern world at least), the compiler will know how to build the stack when calling listInsertFirst.
Are you sure it is the first parameter that is the problem? To be sure, try changing the parameter type from T to int temporarily. More than likely, the third parameter is actually the problem.
Many compilers don't point at the problem in these sorts of issues very well.
Try to move the structure definition to the h file, before the typedef.
Define struct T in header, not in .c file;
Choose different names for structure and typedef.

arrays of not yet defined types (incomplete element type)

Is it possible to make an array of declared but not defined types? This is what I would like to do:
typedef struct _indiv indiv;
typedef indiv pop[];
and let somebody else decide what an individual's members actually are by defining the struct _indiv in another .c or .h file (and then linking everything together).
(For the semantics, indiv is an individual and pop is a population of individuals.)
But the compiler complains:
error: array type has incomplete element type
I could replace the second typedef by
typedef indiv * pop;
And use pop like an array by accessing the elements like p[i] (with p of type pop), but if I do that the compiler will complain that
error: invalid use of undefined type ‘struct _indiv’
error: dereferencing pointer to incomplete type
I suppose since typedef struct _indiv indiv is only a declaration, the compiler does not know at compile time (before the linkage) how much space the struct requires and that it doesn't like it, thus forbiding to do what I'm trying. But I would like to know why and if there is a possible way to acheive what I want.
Thanks
If you want this source file to manipulate items of type indiv, then you have 2 choices.
1) Declare the structure, but don't define it. Use only pointers to the structure. Never dereference them:
struct _indiv;
typedef struct _indiv indiv;
typedef indiv * pop;
//sizeof(_indiv) is not known, how many bytes should we allocate?
pop p = malloc(N*unknownSize);
//this line will fail because it does not know how many bits to copy.
p[0] = getIndiv();
2) define the complete structure:
struct _indiv
{
int id;
char* name;
/*...*/
};
typedef struct _indiv indiv;
typedef indiv * pop;
pop p = malloc(N*sizeof(indiv));
//Now this line can work.
p[0] = getIndiv();
The suggestion to define a dummy 'indiv' is a bad one:
--- file1.c
struct _indiv
{
char dummy;
};
typedef struct _indiv indiv;
typedef indiv * pop;
pop p = malloc(N*sizeof(indiv)); //this will allocate N bytes.
//This will generate code that copies one byte of data.
p[0] = getIndiv();
---realIndiv.c
typedef struct _indiv
{
int id;
char* name;
/*...*/
} indiv;
indiv getIndiv();
{
indiv i = /* whatever */;
return i; //this will return 8+ bytes.
}
When you do this, the first file will be manipulating a differently sized item than the "real" indiv struct, and you are sure to get unexpected behaviour.
You are right that the compiler doesn't know the size of incomplete types (in your example, struct _indiv is an incomplete type), which is why you cannot declare a variable of such a type. This includes creating an array of such types.
However, this doesn't really matter, because if you don't have the complete definition of the type, then you can't sensibly access its members anyway: if you write p[i].foo, how do you know if the type actually has a member called foo, and if it does, what type it is?
If you want the struct type's members to be defined in another .c file (this is known as an "opaque type"), then you must only ever create and handle pointers to the struct. Your other .c should contain all the code that actually accesses the struct itself. The file that has only the incomplete type would contain code like:
indiv *i1, *i2;
i1 = new_individual("foo"); /* Create an individual */
i2 = new_individual("bar");
print_individual(i1);
...and the source file with the complete definition of the struct would contain the implementation of new_individual(), print_individual() and so on.
Under this scheme, the easiest way to deal with a population is to make it an array of pointers to indiv structs.
You can only define array of pointers to an undefined type, because you don't know size of that type.
Note that in C language you can define the same struct differently in many places. You can use this technique: Simply define your struct anyhow, then you can freely define and use pointers to that type. And then define the real struct with the same name somewhere else. Also you get the same effect when you simply use arrays of void*.

Why often a struct's tagName differs from the typedef's name?

Sometimes I see code like this (I hope I remember it correctly):
typedef struct st {
int a; char b;
} *stp;
While the usual pattern that I familiar with, is:
typedef struct st {
int a; char b;
} st;
So what's the advantage in the first code example?
You probably mean this:
typedef struct ST {
/* fields omitted */
} *STP;
The asterisk is at the end of the statement. This simply means "define the type STP to be a pointer to a struct of this type". The struct tag (ST) is not needed, it's only useful if you want to be able to refer to the struct type by itself, later on.
You could also have both, like so:
typedef struct {
/* fields omitted */
} ST, *STP;
This would make it possible to use ST to refer to the struct type itself, and STP for pointers to ST.
Personally I find it a very bad practice to include the asterisk in typedefs, since it tries to encode something (the fact that the type is a pointer) into the name of the type, when C already provides its own mechanism (the asterisk) to show this. It makes it very confusing and breaks the symmetry of the asterisk, which appears both in declaration and use of pointers.
It's a habit that stems from the time when typedef names and struct tagnames were in the same namespace. See http://blogs.msdn.com/oldnewthing/archive/2008/03/26/8336829.aspx
I think you are talking about :
typedef struct{
int a;
char b;
} object, *objectPointer;
This means that (new) type objectPointer is a pointer to struct (object) defined above. Its easy to declare pointers to object struct this way. For instance,
objectPointer A = (objectPointer)malloc(sizeof(object));
A->a = 2;
Now, A is a pointer to struct object and you can access its variables as described above.
In case, objectPointer was not defined,
struct object *A = (struct object *)malloc(sizeof(object));
A->a = 2;
So, I guess objectPointer is more intuitive and easy to use.
I hope that the first code would say a compiler error ,
I see no good reason for the typedef name be different from the tag name.
Now, the reason for which the tag name needs to be typedefed if you don't want to use
struct tag v;
but
tag v;
is probably an historical one. For as long as I remember, C had typedef but I don't know if it was true when struct have been introduced (handling of typedef is a nuisance in the C grammar). In the old code I've seen, using typedef for struct isn't done, and there are things like unix
struct stat;
int stat(const char*, struct stat*);
which would break with an automatic typedef. One those are introduced, changing is quite difficult (yes, C++ has automatic typedef but C++ has special wording to handle that case of overloading and it would be yet another complication).

Resources