C circular dependency with headers - c

I am working on a project where I have to follow guidelines on the organization of the files and I can't get it to compile.
To simplify it I have a main.h where I HAVE to define bool and some symbols to go along with it:
#ifndef main_h
#define main_h
#include <stdio.h>
#include "test.h"
typedef unsigned char bool;
#define TRUE 1
#define FALSE 0
#endif /* main_h */
Then the main.c HAS to use a type "num_seconds_t" and a function "test()", both of which have to be in a seperate file from main.
so I have my test.h:
#ifndef test_h
#define test_h
#include <stdio.h>
#include "main.h"
typedef int32_t num_seconds_t;
bool test(num_seconds_t var);
#endif /* test_h */
and my test.c:
#include "test.h"
bool test(num_seconds_t var){
num_seconds_t test = var;
return TRUE;
}
I don't think main.c would have any affect on this issue.
The error states unknown type "bool" in my test.h file, and I kind of understand why as when it hits the include for "test.h" within the main.h it starts going through that file before it has defined bool in main.h, then since main.h has "#ifndef main_h" when it hits "#include "main.h"" in the test.h it skips this and continues reading so bool never gets defined until after the test.h is done being read.
I am not sure if my understanding is correct, but what is the proper way of solving this. By simply moving the "#include "test.h"" to after the definition of bool it will compile, but in my big project I have many files that intertwine and coordinating the order of including these files would be very tough if not impossible.
Thanks

I'll present 3 solutions:
1) Your best option is to not #include test.h in main.h, since you don't need anything defined in test.h in main.h (you do need stuff from test.h in main.c, so test.h should be #includeed in main.c). This is good practice in general, as described in the comments (you don't want to #include something you don't need).
2) Your second best option is to move things from test.h and main.h to another file. In this case, you'd want to move your typedefs and #defines to another file like so:
typedef unsigned char bool;
#define TRUE 1
#define FALSE 0
typedef int32_t num_seconds_t;
and then include this file in main.h and test.h (or just in test.h because `main.h doesn't need these typedefs).
3) Your last and worst option is to carefully choose the order in which you include things. This is your worst option, since it gets very unwieldy with a large project, but I will show it nonetheless.
Leaving all your other files the same and doing:
// main.c
#include test.h
as the only include in main.c will solve your problem. When you try to compile this, only test.h will be #includeed in main.c. This will then include main.h, which has the typedefs you need for test.h. main.h won't include test.h again, since it has already been included. This is okay, because main.h doesn't actually need test.h.
You could also move your #include in main.h below your typedefs and include main.h in main.c. As I mentioned, however, option 3 is not a good option.
You should really do some combination of options 1 and 2 (in general, not just for this project).

Related

how to use a struct defined in a certain header file from another header in C?

I have two headers files, stack.h
#ifndef __STACK_H__
#define __STACK_H__
typedef struct StackElement_
{
int value;
struct StackElement_ *next;
} StackElement, *Stack;
/*----------------------Prototypes----------------------*/
Stack new_stack();
void push_to_stack(Stack *, int);
int pop_stack(Stack *);
int peek_stack(Stack);
int stack_length(Stack);
void print_stack(Stack);
Bool is_empty_stack(Stack);
void clear_stack(Stack);
/*------------------------------------------------------*/
#endif
and utils.h
#ifndef __UTILS_H__
#define __UTILS_H__
#define INT_MIN -2147483648
/*------------------------Typedef-----------------------*/
typedef enum Boolean_ {
FALSE,
TRUE
} Bool;
/*------------------------------------------------------*/
#endif
In stack.h, I need to know Bool but when I include utils.h in stack.c, the structure is still not known in stack.h. How to do this without having to define it directly in stack.h?
You need to include utils.h in stack .h (not stack.c). The #include statements are part of the C macro language, which is a simple pre-processor. It literally takes the file given as the filename (#include filename) and inserts it into your program (during the pre-processor stage of the compile).
A source file or include file should include all files necessary.
So if stack.h is dependent on declarations in util.h, then you should #include "util.h" in stack.h. That way, any module that includes stack.h doesn't need to worry about also including util.h and putting it in the right order.
If a module decides to include both that should be fine as well. The include guards you've added should address that.
You didn't show the source of stack.c, but you most likely included stack.h before util.h. That would explain your issue since the definitions needed by stack.h appear after them instead of before.

C header file #ifndef #include error

I'm trying to figure out, how to use C headers with #ifndef and #include.
Lets say I have these two header files:
headerA.h:
#ifndef HEADERA_H
#define HEADERA_H
#include "headerB.h"
typedef int MyInt;
TFoo foo;
... some other structures from headerB.h ...
#endif
headerB.h
#ifndef HEADERB_H
#define HEADERB_H
#include "headerA.h"
typedef struct foo{
MyInt x;
} TFoo;
#endif
headerA.c
#include "headerA.h"
... some code ...
headerB.c
#include "headerB.h"
... some code ...
When compiling headerB.c, it says
In file included from headerB.h,
from headerB.c:
headerA.h: error: unknown type name ‘MyInt’
I think, it's becouse when headerB.h is compiling, it defines HEADERB_H and then, when headerA.h wants to include headerB.h, the #ifndef HEADERA_H is false = skips including.
What is the best practice here? I just read, that best practice is to do all #include directives in header files, but in this situation it looks like a problem.
EDIT: Ok, sorry for misleading you. This is just and example from bigger project with more files.
You have a circular dependency. Header file headerA.h depends on headerB.h which depends on headerA.h and so on and on.
You need to break that dependency, for example by not including headerB.h in headerA.h. It's not needed (nothing in headerA.h needs anything from headerB.h).
If you have to include headerB.h (as stated in your recent edit) then you first should reconsider how you use your header files, and what definition you place where. Perhaps move the definition of MyInt to headerB.h? Or have more header files, like one for type-aliases (like your MyInt which I personally see no use for), one for structures and one for variable declarations?
If that's not possible then you could try by changing the order of definitions and the include, like
#ifndef HEADERA_H
#define HEADERA_H
// Define type alias first, and other things needed by headerB.h
typedef int MyInt;
// Then include the header file needing the above definitions
#include "headerB.h"
TFoo foo;
... some other structures from headerB.h ...
#endif
Just drop the line
#include "headerB.h"
from file headerA.h

Linking .h files with .c with #ifdef header guards

im having trouble linking .h and .c files, i've also read some threads regarding this problem and all of them is a bit vague and still i can't fully grasp the concept of it, and im having a lot of linking problems, Say i have b.c and b.h which i will use in a.c, and im confused whether to include b.h both a.c and b.c cuz b.c itself needs to know the structure defined in b.h, i have some function which has its prototype in b.h and is defined in b.c which also use the structure in b.h, im am not including b.h in b.c cuz as what i know b.h is more like an interface to a.c which will use the functions in b.c... Here a more clear example
b.h file
typedef struct{
int x, y;
}myStruct;
void funct1(myStruct);
void funct2(myStruct);
b.c file
void funct1(myStruct x)
{
//do something
}
void funct2(myStruct y)
{
//do something
}
a.c file
#include "b.h"
int main()
{
myStruct x;
funct1(x);
funct2(y);
return 0;
}
Executed the command in cygwin: gcc b.c a.c -g
Now the confusing part, i have a linking error wherein when b.c is compiled it can't detect the structure and the prototypes in b.h. Cuz all i know is that b.h is used to link b.c from a.c but when both .c is compiled it seems that b.c can't find its strucutre and prototypes,
Why didn't i include b.h in b.c?
Answer: Cuz as what i know, b.h is already included in a.c and when i include it again in b.c, i'll be doing double inclusions <--- thats what i learn so far and i know there is #ifdef but it seems it won't work, maybe i still don't know how to use it, if you know please feel free to discuss this.
If you have any idea as to how to go about this feel free to tell me some.
there is a #ifdef directive but i can't seem to have any idea how to do this.
NOTE: ASSUME THAT ALL ABOVE CODES IS SYNTACTICALLY CORRECT if there are any misspelled word please ignore, i'm only after the inclusions between .h and .c
You do indeed need to #include b.h in b.c. Each file is compiled separately before the linker takes over, so it doesn't matter that you have included b.h in a.c, because b.c is compiled by itself and has no idea about the contents of b.h unless you include it.
Here's an example of a #include guard
// some_header_file.h
#ifndef SOME_HEADER_FILE_H
#define SOME_HEADER_FILE_H
// your code
#endif
When some_header_file.h is included anywhere, everything in between the #ifndef and the #endif will be ignored if SOME_HEADER_FILE_H has been defined, which will happen on the first time it is included in the compilation unit.
It is common practice to name the #define after the name of the file, to ensure uniqueness within your project. I like to prefix it with the name of my project or namespace as well, to reduce the risk of clashes with other code.
NOTE: The same header file CAN be included multiple times within your project even with the above include guard, it just can't be included twice within the same compilation unit. This is demonstrated as follows:
// header1.h
#ifndef HEADER_H
#define HEADER_H
int test1 = 1;
#endif
// header2.h
#ifndef HEADER_H
#define HEADER_H
int test2 = 2;
#endif
Now let's see what happens when we try to include the above two files. In a single compilation unit:
// a.cpp
#include "header1.h"
#include "header2.h"
#include <iostream>
int main()
{
std::cout << test1;
std::cout << test2;
};
This generates a compiler error because test2 is not defined - it is ignored in header2.h because HEADER_H is already defined by the time that is included. Now if we include each header in separate compilation units:
// a.cpp
#include "header2.h"
int getTest2()
{
return test2;
};
// b.cpp
#include "header1.h"
#include <iostream>
int getTest2(); // forward declaration
int main()
{
std::cout << test1;
std::cout << getTest2();
};
It compiles fine and produces the expected output (1 and 2), even though we are including two files which both define HEADER_H.
You need to include b.h in all files that uses the structures that are defined in b.h. So you need to put a #include <b.h> in both files. To avoid that b.h is loaded several times, you need the directives #ifdef. In your case:
b.h
#ifndef B_H
#define B_H
typedef struct{
int x, y;
}myStruct;
void funct1(myStruct);
void funct2(myStruct);
#endif
and b.c:
#include "b.h"
void funct1(myStruct x)
{
//do something
}
void funct2(myStruct y)
{
//do something
}
Proper coding would have you include b.h in b.c.
Here is a header guard that should work:
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
//header file
#endif
Put your declarations where the comment is, and include everywhere you need to.
EDIT
The way I understand it, is that gcc compiles b.c first, because a.c depends on b.c. But when it compiles b.c first, b.h has not yet been included.
You need to #include b.h in b.c. It is not just an interface for a.c, b.c needs to know the same definitions for its own code as well. Your reason for not including b.h in b.c is wrong. Each .c file is compiled separately from every other .c file. When the compiler is done with a.c, it starts over fresh with b.c. It does not matter that a.c included b.h, because b.c has no concept that a.c even exists. The purpose of a header guard is to prevent a .h file from being processed repeat times if it is included multiple times while compiling a given .c file. Without the guard, declarations would get compiled multiple times, causing errors about multiple declarations of existing symbols.

Most elegant way to share a C array

I have to turn back to (embedded) C after some lengthy time with C++, and have the following problem:
I have a source module which is included a lot of times, let's call it utilities.h and utilities.c
In it, I have an important array, let's call it
#define IMPORTANT_ARRAY_LENGTH 10000
char important_array[IMPORTANT_ARRAY_LENGTH];
I have a lot of other functions in this utilities module, and they all work fine. However, in one of the other source files, let's call it worker.c, I have to use this array. What is the "official", elegant way to do this, without having to put extern char important_array[IMPORTANT_ARRAY_LENGTH] and the macro definition in the worker.c ?
If I do the following:
utilities.h
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
#define IMPORTANT_ARRAY_LENGTH 10000
extern char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
utilities.c
#ifndef _UTILITIES_C_
#define _UTILITIES_C_
#include "utilities.h"
char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
worker.c
#include "utilities.h"
// ...
important_array[0] = 0;
then my array will be an undefined symbol in worker.c. If I don't use the extern keyword in utilities.h, then of course, it's a duplicate symbol. (Strangely, it compiles with just a warning, and I can see from the linker file that the size is allocated multiple times.)
Do I really have to declare my array in worker.c? I want to keep everything clean, and have all declarations in one place only: in a header file. And I want to have the macro definition only once (this is secondary, because I could use a const, but I want the preprocessor to handle it, and not take up place)
What you have is the canonical way to do it: have an extern declaration in the header file, and define the variable in the .c file.
my array will be an undefined symbol in worker.c
No, it won't. Your code will compile and link just fine.
I often put the definition in the header (this is frowned upon, I know).
It keeps the definition and declaration close together, which is a Good Thing.
/* file.c */
#define FILE_C 1
#include "file.h"
.
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#define BIG_SIZE 13
#if FILE_C
char the_array[BIG_SIZE];
#else
extern char the_array[BIG_SIZE];
#endif
#endif /* FlLE_H */
.
/* other_file.c */
#include "file.h"
There is no risk of doing it wrong: the linker will complain if you do it wrong.
BTW a similar way to basically do the same, but maybe a bit more readable, is:
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#if FILE_C
#define EXTERN /**/
#else
#define EXTERN extern
#endif
#define BIG_SIZE 13
EXTERN char the_array[BIG_SIZE];
...
#undef EXTERN
#endif /* FlLE_H */
Having one declaration (extern...) in each translation unit and exactly one definition is the most elegant way to do this.
So leave the extern char important_array in the header and char important_array in one of the .c files.
Create a new function at utilities.c called something like "get_important_array" that just returns a pointer to array and put the prototype at utilities.h. After that, when you put the utilities.h at worker.c you'll have important_array access in a simple, and organized way.

How does inclusion of header file happen?

I have a plain C code with *.c and *.h files in the workspace.
I have a header file 1.h declaring some structure as
struct my1
{
int a;
..
..
}my_t;
But when i try to declare a variable of type struct my1 in another header file 2.h as follows:-
struct my1 variable1;
It gives error at this declaration point.
Looks like my1 is undefined here in 2.h file.
In file 1.h I need to include 2.h, so in file 2.h I cannot include 1.h, for fear of recursive inclusion.
My question is:-
What do i need to declare to resolve the compilation error in this case?
This whole thing made me think about further questions about header file inclusions.
How are the header files included, in what order, which header file first then which one?
Will recursive inclusion of header files cause errors one file including other and other including first?
Could not post the actual code snippets for some security reason, so sorry if the question somewhat poses some readability problems.
You should start by putting an inclusion lock in all your .h files (this is called an include guard):
#ifndef ONE_H
#define ONE_H
//rest of header
#endif //ONE_H
That way you can include it multiple times.
Second:
typedef struct my1 { int a; .. .. }my_t;
You need a typedef in C (not in C++)
The headers are included in the order of inclusion.
If you compile a file abc.c which starts with:
#include "a.h"
#include "b.h"
then a.h will be included first, then b.h.
You could think of it, as if you paste the code in the file. It is included at that point.
It's like the folks said before.
I just want to add that sometimes even #ifdef won't help you.
//file1.h
#ifndef F1
#define F1
#include "file2.h"
struct file1st {
struct file2st *ptr;
};
#endif
//file2.h
#ifndef F2
#define F2
#include "file1.h"
struct file2st {
struct file1st *ptr;
};
#endif
//main.c
#include "file1.h"
#include "file2.h"
/*
This will give you an error of **struct file1st not defined**
Let's see why:
1) file1.h is included
2) file1.h includes file2.h before it declares anything
3) the definition of struct file2st occurs and it uses struct file1st which isn't declared yet
*/
int main(int argc, char* argv[]){
struct file1st st1;
struct file2st st2;
return 0;
}
The way to work this out is:
//file1.h
#ifndef F1
#define F1
struct file2st;//just declare, it will be defined later.
struct file1st {
struct file2st *ptr; // ok, compiler KNOWS the size of struct file2st*(pointer)
struct file2st file2Var;// NOT ok, compiler doesn't know sizeof(struct file2st)
};
#endif
//file2.h
#ifndef F2
#define F2
#include "file1.h"
struct file2st {
struct file1st *ptr;
};
#endif
Header files are included in the order of include directives. Once the compiler sees an include directive it opens the file to include and simply inserts all of its contents into the including file.
If the included file has include directives inside, the same is done for them. This process continues until all of the include directives have been processed.
Only after that the compilation is started.
That's why if any file is included more than once (A included B and C; both B and C include D for example) you'll often see compiler complaining about redefinitons. To resolve this add inclusion locks (aka include guards) - the ifdef directives.
//file Header1
#ifndef Header1Guard
#define Header1Guard
// all the header text here
#endif
I second the guard suggestion.
I religiously use the following header template:
#ifndef HELLOWORLD_H_
#define HELLOWORLD_H_
// Header stuff here.
#endif // HELLOWORLD_H_
When the compiler see's an #include, it simply replaces that line with the contents of the header file (minus any processed directives in the header). So, that means you can include the file in as many places as you like without risking recursive includes.
Every header file is included in every translation unit (source file) in which there is an include directive for it. This is intended, and will happen even with inclusion guards -- every translation unit that uses your struct needs to know how that struct is defined so that it can be laid out in memory the same way throughout all the translation units of your app. The inclusion guards just prevent it from being included multiple times within one translation unit. Include files will be included in the order you include them within that translation unit (and they'll be recursively included if include files include other files... as others have said). The order of translation units being compiled is up to you (or your IDE) to specify to the compiler. It shouldn't matter what that order is, however, since every translation unit is completely independent until it gets to the linking phase of the build process.
It's been a while since I worked with C, but I think what you want to do is forward define my1.
In 2.h, try putting this near the top:
struct my1;
Sorry, I can't answer your other two questions.
// Header1.h
typedef struct tagHeader1
{
} Header1;
// Header2.h
struct Header1;
// Header2.c
#include "Header1.h"
Note: This only works for pointers (and in c++, references). If you have a reference to a complete object, the compiler will need to know about it.

Resources