0

I'm new in C, one thing is driving me crazy is how to make visible to all files of my project a typedef struct...Maybe is a design error, not sure...

The stage is I have a typedef struct like this

// File header.h
typedef struct stu {
    char name[60];
    char id[10];
    int age;
    float puntuation;
} Student;

The I have several data structures where I want to use this typedef, I have a Stack, a hash table and a binary tree...I include all in main.c

// File main.c
#include "header.h"
#include "hashtable.h"
#include "stack.h"
#include "tree.h"

I need to use Student in hashtable and stack, and also need to use another typedef defined in stack in the tree but I'm not able to get it working...

The compiler says type name 'stack_def' unknown in tree.h and tree.c, if I exclude stack.h in main.c and include it in tree.h then it says the same in stack.h for the typedef Student.

Can someone, please, tell me what's going on here?

Thanks.

josecash
  • 339
  • 4
  • 19
  • 2
    The compiler is definitely telling *you* what is wrong, but you are not telling *us*. – Jon Aug 18 '13 at 18:30
  • 4
    When you ask for help with any computer problem, you **must** state what is going wrong and what you desire instead. E.g., if there is a compiler error message, show it (in which case, the desired behavior is no message). If the program runs but shows the wrong output, show the wrong output and show what you desire. Whenever possible, you should show all the source code and input needed to reproduce the problem. That may require deleting parts of the program to reduce it to a [short, self-contained, compilable example](http://sscce.org/). – Eric Postpischil Aug 18 '13 at 18:33
  • Allright I missed that, it is now #included... :) – josecash Aug 18 '13 at 18:36
  • 1
    See [Should I use `#include` in headers?](http://stackoverflow.com/questions/1804486/should-i-use-include-in-headers/1804719#1804719) and answers linked from there for more information. – Jonathan Leffler Aug 18 '13 at 19:14

2 Answers2

1

My psychic powers tells me that you have a circular reference in your header files—you have two header files a.h and b.h, where each #includes the other (or possibly a longer chain, such as a.h including b.h, which includes c.h, which includes a.h).

To fix that, you need to remove unnecessary inclusions—only have each header file include the bare minimum of other headers it needs to compile correctly. If you only need to use pointers to certain types (without the full definitions), you can use forward declarations instead of including the types:

// Forward declaration of `stu' -- we can now use pointers to `stu', but not
// any of the members of `stu' etc.
struct stu;

// Pointer to `stu' -- OK
struct other_struct
{
    struct stu *a_pointer;
};

// Function parameters and return value of `stu' -- OK
struct stu function_taking_stu_and_returning_stu(struct stu arg);

// `stu' instance -- ERROR
struct another_struct
{
    struct stu not_a_pointer;  // ERROR -- `stu' is incomplete
};

Once you remove the circular dependencies from your header files, then it should compile properly.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
0

In each file, whether it is a header file or a source file, use #include to include each header file that declares something the header file or source file needs. For example, if tree.h makes use of the Student type, then, in tree.h, put an #include directive that includes the header file that declares the Student type. You should not be guessing here headers are included. It is a simple rule: If a file uses something declared in a header, then include that header in that file.

Obviously, if each file includes the headers that declare the things the file needs, then nothing the file needs will be undeclared. So those compiler error messages should vanish.

After doing that, one problem you can encounter is a loop of inclusions, where some file includes a header that includes the first file again (possibly indirectly, through a chain of included files). In simple projects, no such loop should occur; no header should both depend on something declared an another header and declare something that the other header needs. However, if you have such a loop, you can break it by making a second inclusion of a header have no effect, by using what are called “header guards”:

// Test whether this header has not been included before.
#if !defined ThisHeaderFileName_h

// Define a symbol so we know this header has now been included.
#define ThisHeaderfileName_h

… // Put body of the header file here.

// Close the #if.
#endif
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312