Forward declaration error I'm having trouble making sense of - c

Header file declaration:
typedef struct Queue *QueueP;
C File implementation:
struct Queue
{
char *head;
char *tail;
QueueItemT item; //char typedef from the header file, not what's giving error
int SizeL;
int sizeP;
int QueueSize;
};
C main file:
#include <stdio.h>
#include <stdlib.h>
#include "Queue1.h"
int main()
{
struct Queue queue;
QueueP myQueue = &queue;
return 0;
}
I am getting errors on the following lines with the following messages respectively:
struct Queue queue;
^
Main : variable has incomplete type 'struct Queue'
typedef struct Queue *QueueP;
^
Header : note: forward declaration of 'struct Queue'
Any idea what might be causing these errors? I'm new to working with multiple files and header files in C, so I'm really having trouble wrapping my head around these errors. Any help would be great, thanks!!

You put structure definition into a c file. This is not how it works: you need to put the definition into the header.
This is because a definition of a struct is not an implementation. C compiler needs this information in order to process declarations of the struct correctly. A forward declaration lets you define a pointer to your struct; declaring a struct itself requires a full definition.
If you would like to keep the details of your struct private, put it into a private header file. Include the public header file from your private header, too:
queue.h
typedef struct Queue *QueueP;
queue_def.h
#include "queue.h"
struct Queue
{
char *head;
char *tail;
QueueItemT item; //char typedef from the header file, not what's giving error
int SizeL;
int sizeP;
int QueueSize;
};
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "queue_def.h"
Now your project should compile without problems.

Actually, the reason I was getting forward declaration problems was because I was trying to access the struct (that was declared in the .c file) from within the main file.
Not only was this bad programming practice, the desired feature of the project was that the end user (i.e. the person using the interface and implementation to build their 'main.c' file) should have no idea what kind of struct was being used, they should simply be able to build a queue with the functions given and not know what was going on behind the scenes.
D'oh!!!

Related

How can I fix an forward declaration warning in a structure

I have several structures, and I keep getting a warning message. I've been trying for several hours to kick it out, but I can't.
I would really appreciate the help.
This is the Student struct in the Student.h header:
#ifndef __STUDENT_H__
#define __STUDENT_H__
#include "Teacher.h"
#include "ClassRoom.h"
struct Teacher;
struct ClassRoom;
typedef struct {
char * name;
struct ClassRoom *myClassRoom;
struct Teacher *myTeachers[3];
} Student;
void setTeacherDynamic(struct Teacher *t, struct Teacher* tt);
and this is the Student.c source code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Teacher.h"
#include "Student.h"
struct Teacher;
void setTeacherDynamic(Teacher *t, Teacher* tt)
{
strcpy(t->name, tt->name);
t->myClass = NULL;
}
The warning message is:
The problem is with the function setTeacherDynamic(), and I don't know how to fix it.
The Teacher struct:
and this is when I'm calling to the function, also in Student.c
You have multiple problems:
The first is that since you have forward declarations in Student.h you don't need to include Teacher.h or ClassRoom.h. And in the source file Student.c you can remove the forward declaration you have.
The second problem is that you don't actually have a struct Teacher. You have a Teacher type-alias for an anonymous structure. You should declare the actual structure for the forward declarations to work:
typedef struct Teacher { ... } Teacher;
You should do these changes for all your source and header files.

Why does my struct have to be declared as a pointer?

I'm learning how to create header files and separate the implementation while also starting to learn about how to create a linked list. I created linked_list.h, linked_list.c, and main.c files. In main.c I get an error when trying to create the struct I typedef'ed unless I create it as a pointer, then it works. I don't understand why this is, could someone please explain this?
linked_list.h:
#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_
typedef struct ListNode_ ListNode;
#endif // LINKED_LIST_H_
linked_list.c:
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
struct ListNode_ {
int data;
ListNode *next;
};
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
int main() {
ListNode node1; // why can't I do this?
ListNode *node2; // but this works
}
This is because despite how both ListNode and ListNode_ have been declared, only ListNode_ has been defined. The compiler doesn't know what a ListNode object can contain or do.
Yes, you can have pointers to ListNode. However, you cannot use them. Try typing
//ListNode node1; // why can't I do this?
ListNode *node2; // but this works
node2->foo();
and you'll get the same compilation error message about an incomplete type. It's ok only to have the pointer stored somewhere because it's only an address after all and the program only needs to know what it points to.
And yes, you don't use node1 but it still gives you an error. Why? Because the program will automatically have to allocate space for node1 and it has no idea how much that space should be. Not to mention it's supposed to automatically call its constructor, which, again, isn't defined.
This is also why here
struct ListNode_ {
int data;
ListNode *next;
};
you're allowed to have that pointer.
I'm ignoring the fact that the files haven't even been linked properly because that was discussed in the comments and it has nothing to do with this issue anyway.
Since you've used multiple files, you've to be a little more careful to make sure that all files have the same view of your struct. In particular, you should consider defining struct ListNode and typedefing it inside the header file linked_list.h itself, as so:
struct Listnode_ {
int data;
struct ListNode_ *next;
};
typedef struct Listnode_ Listnode;
The reason you can't declare the actual variable is because main.c doesn't know what its structure is, so it can't allocate memory for it. You CAN however declare a pointer, because all pointers have the same structure internally, no matter what type they are. This is called the PIMPLE concept (Pointer to IMPLEmentation), where you can declare pointers pointing to some implementation even if you don't know what it is - it's a form of abstraction that C offers.
You need to think about what the compiler does when you declare a ListNode in main.c. It sees the typedef to struct ListNode_, but it doesn't know what struct ListNode_ is when it is compiling main.c. To fix this, you need to move the definition of struct ListNode_ to linked_list.h.
The declaration of a pointer to ListNode works because it is possible to declare a pointer to an object of an unknown size, such as struct ListNode_ in this case. However, if you wish to declare a full-blown ListNode, the compiler needs to know what size it is. But since the compiler compiles each source file separately, it does not know about the struct ListNode_ in linked_list.c, and thus throws an error.

Why this "dereferencing pointer to incomplete type" error?

I know this question is getting old, but I can't seem to understand what's wrong with my code.
I have a tree.c file with the following struct tree, and this file includes a header file in which is declared a pointer to this type of struct:
tree.c
#include "tree.h"
typedef struct tree
{
char desig[200];
int num;
tree_ptr left, right, subtree;
} Tree;
tree.h
#ifndef ___TREE_H___
#define ___TREE_H___
typedef struct tree *tree_ptr;
#endif
When I try to access some instance of this struct in another source file, the compiler gives me the "dereferencing pointer to incomplete type" error:
insert(..., instance->subtree);
What's wrong?
Try making the following your tree.h file:
#ifndef tree_h_
#define tree_h_
typedef struct tree
{
char desig[200];
int num;
struct tree *left, *right, *subtree;
} Tree;
typedef struct tree *tree_ptr;
#endif
and removing the declaration of Tree from you implementation file. Due not showing a small,working MCVE or a SSCCE, I can't test the above solution in your specific case, however the following simplistic program compiles (gcc -ansi -pedantic -Wall tree.c -o tree_test) without warning or error :
file tree.c
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
int main(int argc, char* argv[])
{
Tree root;
root.left = malloc(sizeof(Tree));
root.right = malloc(sizeof(Tree));
root.subtree = NULL;
if((NULL != root.left) && (NULL != root.right))
{
root.left->left = NULL;
root.left->left = NULL;
root.right->left = NULL;
root.right->right = NULL;
}
return 0;
}
This was tested using gcc version 4.8.2 on a Centos 7 system.
N.B. I've presented only minimalist error checking, no error handling and no clean-up code to keep the example short. Certainly in your code you should insure complete error checking, error handling and clean-up.
Your header file has only definition for pointer type "tree_ptr". Pointers are always 4 bytes on 32 bit machines no mater what they are pointing too. So as long as you are not accessing the members of "struct tree" you are okay i.e when you assign value to pointer of type "tree_ptr" or when checking if the pointer of type "tree_ptr" is not NULL. These kind of operations don't require complete struct definition. But if you want to access the members of this struct your code needs the struct definition in the scope. Structs are not like functions so you cant declare them them in the header and define in the .c file. So I suggest you move your struct definition to your header file.
The other source files cannot see your tree.c and have absolutely no knowledge of what's inside your tree.c. All they can see is tree.h which declares
typedef struct tree *tree_ptr;
And that declares struct tree as an incomplete type.
Your struct tree is a complete type inside tree.c and only inside tree.c. In all other .c files it is an incomplete type. If you want it to be complete in all source files that include tree.h, you will have to move the full declaration of struct tree to tree.h.

C Typedef - Incomplete Type

So, out of the blue, the compiler decides to spit this in face:
"field customer has incomplete type".
Here's the relevant snippets of code:
customer.c
#include <stdlib.h>
#include <string.h>
#include "customer.h"
struct CustomerStruct;
typedef struct CustomerStruct
{
char id[8];
char name[30];
char surname[30];
char address[100];
} Customer ;
/* Functions that deal with this struct here */
customer.h
A header file for customer.h
#include <stdlib.h>
#include <string.h>
#ifndef CUSTOMER_H
#define CUSTOMER_H
typedef struct CustomerStruct Customer;
/* Function prototypes here */
#endif
This is where my problem is:
customer_list.c
#include <stdlib.h>
#include <string.h>
#include "customer.h"
#include "customer_list.h"
#include "..\utils\utils.h"
struct CustomerNodeStruct;
typedef struct CustomerNodeStruct
{
Customer customer; /* Error Here*/
struct CustomerNodeStruct *next;
}CustomerNode;
struct CustomerListStruct;
typedef struct CustomerListStruct
{
CustomerNode *first;
CustomerNode *last;
}CustomerList;
/* Functions that deal with the CustomerList struct here */
This source file has a header file, customer_list.h ,but I don't think its relevant.
My Problem
In customer_list.c, at the line with the comment /* Error Here */, the compiler complains about field customer has incomplete type.
I've been googling this problem all day, and now im at the point of pulling out my eyeballs and blending them with strawberries.
What is the source of this error ?
Thanks in advance :)
[P.S. if I forgot to mention something, let me know. Its been a stressful day for me, as you might tell ]
Move the struct declaration to the header:
customer.h
typedef struct CustomerStruct
{
...
}
In C, the compiler needs to be able to figure out the size of any object that is referenced directly. The only way that the sizeof(CustomerNode) can be computed is for the definition of Customer to be available to the compiler when it is building customer_list.c.
The solution is to move the definition of the struct from customer.c to customer.h.
It seems that something like
typedef struct foo bar;
won't work without the definition in the header. But something like
typedef struct foo *baz;
will work, as long as you don't need to use baz->xxx in the header.
What you have is a forward declaration of Customer structure that you are trying to instantiate. This is not really allowed because compiler has no idea about the structure layout unless it sees it definition. So what you have to do is move your definition from the source file into a header.

Simple header file visibility confusion in C

I have a strange problem in C about including header files.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "location.h"
int waste_new_line();
int main()
{
location *crossroads = malloc(sizeof(*crossroads));
...
location.h
typedef struct Location_Struct location;
location.c
typedef struct Location_Struct {
int ID;
char *name;
char *description;
} location;
int setup_location(location* l, char* name)
{
...
Now this isn't working because
location *crossroads = malloc(sizeof(*crossroads));
is throwing an error:dereferencing pointer to incomplete type meaning that it can see the contents of location.h, yet it doesn't seem to be aware of location.c...
I've looked around and all the tutorials I've seen say that the linker will link both files together.
EDIT:
I have altered the code to include an initializer inside location.c as so:
main.c
...
#include "location.h"
int waste_new_line();
int main()
{
location *crossroads = initialize_location();
....
location.h
typedef struct Location_Struct location;
location* initialize_location();
location.c
...
typedef struct Location_Struct {
int ID;
char *name;
char *description;
} location;
location* initialize_location(location* l)
{
return malloc(sizeof(location));
}
...
This is still throwing the same error, yet only when I try and access the members of crossroads using:
crossroads->description
this will throw the deferencing to incomplete type error.
EDIT 2: For now I've decided to just put the struct definition in the header file...
This behaviour is expected. When you #include "location.h", only the header file is visible to the compiler. The location.c file comes along later, at link time.
You have two options:
Add a function, which you declare in location.h and define in location.c, which does the necessary malloc and returns a pointer.
Move the full definition of the struct to the header file.
The main file knows about a struct called Location_Struct (and a typedef). It has no idea how big it is, thus you can't apply sizeof to it.
Since you are effectively hiding the layout and the implementation of Location_Struct it makes sense to provide a "constructor" that allocates it.
EDIT
It seems I have to mention that by "constructor" I mean an ordinary function that has access to the implementation of the structure and can allocate and possibly pre-populate the object.
You need to put the definition of Location_Struct in the header file location.h. The compiler would not "see" the other source file (unless it were #include'd, which would not typically be a good idea).

Resources