C - Headers including each other - c

I have a file game.h which has this declaration
typedef struct Enemy {
...
}Enemy;
And a function
void moveEnemy(Level* l, Enemy* enemy){
...
}
Level is declared on levels.h, so in game.h I have:
#include "levels.h"
Everything was perfect, until I had to use Enemy in levels.h.
So, in levels.h I added:
#include "game.h"
And now I get a compilation error:
game.h:34:2: error: unknown type name ‘Level’
Level* level;
^
I have include guards on both .h
I don't know why I can't have on file including another.
What can I do?

Just add a forward declaration, like this in game.h before the function,
typedef struct Level Level;
since it's just a pointer to Level this will do it.

Related

struct declared in tools.h and defined in tools.c. Can't link them to main.c

file tools.h:
//some macro definitions
struct name;
//other function prototypes
file tools.c:
#include "tools.h"
struct name
{
FILE *src;
int value;
}
//definitions of functions declared in tools.h
file main.c:
#include <stdio.h>
#include "tools.h"
int main()
{
struct name *ptr;
ptr = malloc(sizeof(struct name));
ptr->FILE = fopen(filename, "r");
ptr->value = 12;
...
}
At first, I built tools.o by using:
$ gcc tools.c -c
Without any error or warning, tools.o was built in the current directory.
Now, I tried to build executable by using:
$ gcc main.c tools.o -o exe
and I got errors of same type (all the errors were of same type, caused due to accessing the struct element). Here's the sample of that error I got:
main.c: In function ‘main’:
main.c:17:22: error: invalid use of undefined type ‘struct name’
17 | buffer = malloc(ptr->value+1);
Please explain why this happened and what wrong I did while linking or in my code.
tools.h file
#ifndef TOOLS_H
#define TOOLS_H
#include <stdio.h>
struct name
{
FILE *src;
int value;
};
int foo(struct name*);
struct name *bar(double, FILE*, const char *); //prototypes of functions defined in tools.c
#endif
tools.c
#include "tools.h"
int foo(struct name*)
{
/* ... */
}
struct name *bar(double, FILE*, const char *)
{
/* ... */
}
Looks like you have some confusion with regards to forward declaration of a structure and a structure declaration (which defines a type).
From Forward declaration:
a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
In tools.h, this
struct name;
is forward declaration of structure struct name. Note that, it declares an incomplete type because the specification [list defining the content] of struct name is unknown at this time.
You have included the tools.h in main.c and when compiling main.c compiler does not find the specification of struct name and hence, throwing error on the statements using it.
In tools.c, you are declaring the struct name (which defines a type):
struct name
{
FILE *src;
int value;
};
when compiling tools.c, compiler knows about the specification of structure struct name and hence, it's compilation is successful.
The other post [by #0___________] gives the appropriate way to solve this problem.

Cant send pointer to structure after it moved to a different header file

I have a program spread through 3 different C files, with the 2 header files that come with it. I originally had the header "Player.h" that I used to save the "map" structure (among others):
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
typedef struct map{
float x;
float y;
}map;
/// some other functions and structures///
#endif
I wanted to move it to its own header file, "Map.h" so its with the other map-related functions and structures.
#ifndef MAP_H_INCLUDED
#define MAP_H_INCLUDED
typedef struct map{
float x;
float y;
}map;
#endif
I made the Map.c file as normal, wrote a function in it that would work, but I didn"t call for the function in main.c yet.
I made the "map" data structure in main.c as followed:
#include "Player.h"
#include "Map.h"
int main(){
... /// some other stuff being done
map map;
map.x = 0;
map.y = 0;
... /// more stuff being done
callfunctioninplayer(&map, /// other variables///)
}
so I call the function in player.c, where I also included map.h using #included "Map.h". But after trying to compile it, it gave me an error everywhere where I asked for the map* map structure with the errors:
In file included from ./main.c:10:0:
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
^~~
In file included from ./Map.c:10:0:
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
I checked if map.h was defined everywhere, it is, and I tested it again after putting the map struct back in player.h. Putting it back in player.h worked, but why didn't it in map.h?
I'm sorry if this is asked a lot, I looked through some posts but couldn't find anyone with the same error
It looks like map is being used in Player.h, but Map.h hasn't been included at the point Player.h is included, and presumably you didn't include Map.h in Player.h.
If Player.h needs definitions in Map.h, then you need to #include "Map.h" in Player.h.

include guard does not allow me to declare a type

I encountered such an interesting problem, because of the include guard trigger, the type declared in the header file is not declared.
I have a mutex file.h which describes the mutex_t type, it depends on the thread_t type that is declared in the thread file.h, however, thread_t depends on mutex_t, and the main.c file uses both of these types.
Problem:
when compiling main.c, the thread file is included.h, which includes mutex.h, however, because of the thread.h was already connected, then it rolls out include guard and does not allow declaring the thread_t type in mutex.h
thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
#include "mutex.h"
typedef struct thread
{
int thread_data;
} thread_t;
extern mutex_t* get_mutex();
#endif
mutex.h
#ifndef _MUTEX_H_
#define _MUTEX_H_
#include "thread.h"
#include "stdint.h"
typedef struct mutex {
uint8_t lock_status; //+0
thread_t* waiting_thread_queue[1024];
} mutex_t;
extern thread_t* get_thread();
#endif
main.c
#include "stdlib.h"
#include "stddef.h"
#include "thread.h"
int main(void) {
get_thread();
get_mutex();
return 0;
}
This is the error I get:
emilia#emilia-pc:~/test$ gcc main.c
In file included from thread.h:4,
from main.c:3:
mutex.h:9:5: error: unknown type name ‘thread_t’
9 | thread_t* waiting_thread_queue[1024];
     | ^~~~~~~~
mutex.h:12:8: error: unknown type name ‘thread_t’
12 | extern thread_t* get_thread();
     | ^~~~~~~~
You have a circular dependency between two headers. The thread header needs mutex and vice versa.
The way you have done it doesn't make sense. The thread header declares a function called get_mutex, and vice versa, the mutex header declares a function called get_thread.
Probably, what this points to is that the headers are so closely related, they should be one header.
Anyway, the way we can break a circular dependency is by using a forward declaration in one of the headers.
// child.h
struct parent; // incomplete "forward" declaration
struct child {
struct parent *parent;
};
// parent.h
#include "child.h"
#define MAX_CHILDREN 42
struct parent {
struct child *children[MAX_CHILDREN];
};
The "forward" declaration struct parent doesn't require the parent.h header. The parent.h header picks up that declaration, but it does not interfere with its own declaration, because this is allowed:
struct parent;
struct parent { ... };
Note that _THREAD_H_ intrudes into a reserved implementation namespace. Names beginning with an underscore followed by either a capital letter or another underscore are reserved. Violating this rule is actually undefined behavior, which can have any consequences whatsoever. The implementation can stop translating your program with a diagnostic message. Or it can predefine a macro called _THREAD_H_, so that your own header fails to produce its expected contents.

Is it OK to not include a header file which has a define of struct?

I have a.h:
#include "b.h" // XX
struct A {
int asdf;
struct B *b;
};
extern struct A aaa;
Also b.h
#include "a.h"
struct B {
int asdf;
int ghjk;
}
static inline void sth() { aaa.asdf*** }
It gives following errors:
b.h:17:6: error: ‘aaa’ undeclared (first use in this function)
But if I remove line XX, the compile succeeds.
Is it OK to do that?
The compile might work if you remove that line, but the program won't link.
You have to define aaa somewhere.
Your header files must be surrounded by #ifndef HEADER_H... header guards.
Having two header files that include each other is a sign of bad program design.
The presence of extern anywhere in your code is a sign of bad program design, with very few exceptions.
There are a few cases where you can place a (static inline) function definition inside a header file, but most of the time that means bad program design.
Summary: really bad program design leads to really bad programs.

Proper way to declare and use structures in C project?

I am building a project that I am trying to organize as follows:
main.c
globals.h
structures.h
FunctionSet1.c, FunctionSet1.h
FunctionSet2.c, FunctionSet2.h
etc.
I thought I could define a structure type in structures.h:
struct type_struct1 {int a,b;}; // define type 'struct type_struct1'
then declare a function1() returning a structure of type type_struct1 in FunctionSet1.h:
#include "structures.h"
struct type_struct1 function1(); // declare function1() that returns a type 'struct type_struct1'
then write function1() in FunctionSet1.c:
#include "FunctionSet1.h"
struct type_struct1 function1() {
struct type_struct1 struct1; // declare struct1 as type 'struct type_struct1'
struct1.a=1;
struct1.b=2;
return struct1;
}
Edit: with the corrected code above, the compiler returns
306 'struct' tag redefined 'type_struct1' structures.h
Is the file set good practice ?
What is the good practice to manage the structures ?
In your example, you declare a structure named type_struct in structure.h, then in FunctionSet1.h the structure that you are returning is type_struct, and in the .c it is called struct1.
So i think that the problem is that struct1 and type_struct are not recognized because they have never been defined ...
However, the organization of your files is fine.
Your general structure looks good. One thing you need to do, as zenith mentioned, is to put include guards into your header files. What that is is a set of #define's that make sure that the contents of the header are not included more that once in a given file. For example:
structures.h:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct type_struct1{
int a,b;
};
...
// more structs
...
#endif
FunctionSet1.h:
#ifndef FUNCTION_SET_1_H
#define FUNCTION_SET_1_H
#include "structures.h"
struct type_struct1 function1();
...
// more functions in FucntionSet1.c
...
#endif
main.c:
#inlcude <stdio.h>
#include "structures.h"
#include "FunctionSet1.h"
int main(void)
{
struct type_struct1 struct1;
struct1 = function1();
return 0;
}
Here, main.c includes structures.h and FunctionSet1.h, but FunctionSet1.h also includes structures.h. Without the include guards, the contents of structures.h would appear twice in the resulting file after the preprocesser is done. This is probably why you're getting the "tag redefined" error.
The include guards prevent these type of errors from happening. Then you don't have to worry about whether or not a particular header file was included or not. This is particularly important if you're writing a library, where other users may not know the relationship between your header files.
First of all, you have to declare the structure in your file.h (you can use typedef to create an alias)
typedef struct Books
{
char title[50];
int book_id;
} books;
then, you have to include your file.h in your file.c and declare your variable like this
#include "file.h"
int main()
{
books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
or like this if you didn't use typedef
#include "file.h"
int main()
{
struct Books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
Thank you all.
I read again what you said and found that the code above is now correct.
The error I report is with testing the following main.c
#include "structures.h"
#include "FunctionSet1.h"
void main() {
struct type_struct1 struct2;
struct2=function1();
}
in which structures.h is included again, thus causing the error. Removing the include eliminates the error.
I will now look into header guards to avoid such problems.
Thanks again.

Resources