I wrote a minimal code to test the working of guard macros in C. I read that they prevent the header file to be read again by the compiler if it has done already. Here is my header file:
#ifndef TEST_H
#define TEST_H
#include<stdio.h>
int num=12;
#endif
Here is my main function:
#include"headers.h"
int main()
{
p2();
return 0;
}
Here is the p2 function called in main():
#include"headers.h"
void p2()
{
printf("p2 running\n");
}
While compilation it is giving me error of redefinition of num. Should macro TEST_H not prevent multiple definitions error of num here ?
Also if I replace int num=12; with int num; , without any other modification, It does not show any error. Should int num; must not be a definition of num(as it will be initialized to 0) and compiler should again show same error of multiple definitions of num?
Let me answer to each of your questions:
The macro TEST_H prevents any multiple inclusion of the content of headers.h file in a translation unit, i.e. in a C source file. In your case, it works: you have only one definition of num in each C file. The raised error probably comes from the linker, which finds two definitions of the same variable in the linked code.
If you replace int num=12; with int num;, then it become a tentative definition as commented by #RobertoCaboni: to summarize, you authorize the compiler/linker to consider this instruction either as a definition (the first time it is encountered) or a declaration (the next times it is encountered). So you do not have any more error with multiple definitions. The initialization to 0 will depend on your linker configuration and/or your source code.
Should macro TEST_H not prevent multiple definitions error of num here ?
No. Each c file or translation unit compiled separately and header guard avoids multiple definitions within transaction unit.
In preprocessing stage of compilation all header files declared in a transaction unit are copied,macro's are expanded and many more things are done. refer for more details.
Understand how header guard is working,
//test.h
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
If Multiple includes of same headers,
//main.c
#include "test.h"
#include "test.h"
int main(){
}
Translates as below during per-processing stage of compilation and conditional compilation part of code will be removed.
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
//as __TEST_H__ is already defined subsequent inclusion of test.h has no effect
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
int main(){
}
And Hence compiler will not detect any conflict with multiple definition of num.
Linking takes one or more object files or libraries as input and combines them to produce a single (usually executable) file. In doing so, it resolves references to external symbols, assigns final addresses to procedures/functions and variables, and revises code and data to reflect new addresses (a process called relocation). Which detects multiple instance of the same variable and throws link time error for multiple definition.
Should int num; must not be a definition of num(as it will be initialized to 0) and compiler should again show same error of multiple definitions of num?
There has to be exactly one definition of any functions or initialized global variables, but the definition of an uninitialized global variable can be treated as a tentative definition. C then allows (or at least does not forbid) different source files to have tentative definitions for the same object. (source)
Related
below is the code:
//test.h
...
extern int globalVariable;
...
//test.c
#include "test.h"
...
int globalVariable = 2020;
...
//main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("Value is %d", globalVariable);
}
let's say in a scenario, there are hundreds of variables are declared in test.h and globalVariable is just one of them.
since there are two many variables, I easily makes a typo error in test.c as:
#include "test.h"
int globalVariables = 2020; //extra 's' in the name which contradicts the declaration of its counterpart in test.h
if I compile(only compile,not linking them) test.c, test.h and main.c, it compiles and shows no error. the unresolved error will only occur when linker involved in the linking stage.
But in a large application, I might just write some modules without the need of linking all existing to an executable file, so it would be better the compiler throw an error in the compile stage to indicate the error so I can correct them asap, so how can I let the compiler force the source file implement definition for a header file?
You could also use the preprocessor
test.h:
#ifndef TEST_C_IMPLEMENTATION
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
extern type name;
#else
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
type name = value;
#endif
DEFINE_AND_INIT_VARIABLE(int, globalVariable, 2020);
test.c:
#define TEST_C_IMPLEMENTATION
#include "test.h"
This technique can be taken even further - there are small utility libraries that are shipped as a single include file; you're just to set a macro in one of the translation units to force the implementation to be compiled in there.
The declaration extern int globalVariable; says that the variable exists somewhere, but not necessarily in the current translation unit. So any source file that includes the header containing this declaration will know that the variable exists without needing the full definition.
When you then get to the linking stage is when you'll get the error regarding glovalVariable being undefined. Since the variables is declared in test.h, convention would dictate that the definition would be in test.c. Upon inspecting that file, you would then find that no such variable exists and could then either add it or find the typo and fix it.
I've inherited some code* which declares and defines a struct in a header file (a_A.h). This struct is in the top file of an include hierarchy tree which symbolically looks like:
file: t_T.h (#includes "c_C.h") //defines a struct
file: c_C.h (#includes "h_H.h")
file: h_H.h (#includes "a_C.h")
file: a_C.h (#includes <stdio.h>)
Each header has the appropriate header guards and appear to be non-recursive when looked at as a flat collection of files. However, files c_C.h and a_C.h reside in the same library. While h_H.h resides in a different library. From a library perspective this symbolically appears as:
t_T.h (includes a file from Lib_C)
Lib_C: (includes a file from Lib_H)
Lib_H (includes a file from Lib_C)
which is recursive and is the likely cause of redefinition problems when I compile the code (the linker complains that the struct in file a_C.h is redefined).
1) Did I correctly identify the issue?
2) If so, why? I am guessing that linked objects in a library appear flat to the linker (i.e. they've lost their hierarchy context). And if guessed somewhat correctly then:
3) Should I consider header guards to be limited to the scope of their respective library?
Below is the error statement from the problems window:
symbol "ov5642_1280x960_RAW" redefined: first defined in "./TakePhoto.obj"; redefined in "./ArduCam/ov5642_Config.obj"
Header in ./TakePhoto:
#ifndef TAKEPHOTO_H
#define TAKEPHOTO_H
#include "ov5642_Config.h"
#include "HAL_ArduCAM.h"
...
#endif /* TAKEPHOTO_H_ */
Header in ./ArduCAM/ov5642_Config.h:
#ifndef ARDUCAM_OV5642_CONFIG_H_
#define ARDUCAM_OV5642_CONFIG_H_
#include "HAL_ArduCAM.h"
#include "ov5642_Sensor_Values.h"
....
#endif /* ARDUCAM_OV5642_CONFIG_H_ */
Header in HAL_ArduCAM
#ifndef HAL_ArduCAM_h
#define HAL_ArduCAM_h
#include <stdint.h>
#include "driverlib.h"
....
#endif /* HAL_ArduCAM_h */
ov5642_Sensor_Values.h has the following
#ifndef ARDUCAM_OV5642_SENSOR_VALUES_H_
#define ARDUCAM_OV5642_SENSOR_VALUES_H_
#include <stdint.h>
const struct sensor_reg ov5642_1280x960_RAW[] =
{
{0x3103,0x93},
{0x3008,0x02},
{0x3017,0x7f},
.....
#endif /* ARDUCAM_OV5642_SENSOR_VALUES_H_ */
It seems that the contents of OV5642_Sensor_Values is copied twice, once for TakePhoto and once again for ovV5642_Config despite their header guards. My original thought was that there was a recursive dependencies but didn't find it.
Ok, I've made an example pasted below. There are five files in this example, three files (bar.h, foo.h, foo.c reside in a library), the other two files (foo1.h, foo1.c) do not. Notice that foo.h includes bar.h and that foo1 includes both foo.h and bar.h.
I am conjecturing that the guard headers of bar.h are not preserved when the pre-processor copies into foo.h. Thus when foo1 includes bar.h and foo.h the symbol redefinition arises. So to answer my own question, no, it is not a library issue. Not preserving the header guard seems the likely cause of my problem.
They are pasted below.
/*
* bar.h
*
*/
#ifndef ARDUCAM_BAR_H_
#define ARDUCAM_BAR_H_
#include <stdint.h>
typedef struct regStruct {
uint16_t reg;
uint8_t val;
} regStruct;
const struct regStruct regArray[] =
{
{0x3103,0x03},
{0x3104,0x03},
{0x3008,0x82},
{0xffff,0xff},
};
const struct regStruct tinyArray[] =
{
{0x3106,0x03},
{0x3003,0x82},
{0xffff,0xff},
};
#endif /* ARDUCAM_BAR_H_ */
/*
* foo.h
*
*
*/
#ifndef ARDUCAM_FOO_H_
#define ARDUCAM_FOO_H_
#include <stdint.h>
#include <stdio.h>
#include "bar.h" //including this file causes redefinition
typedef struct Init_Parameters {
//! Select sensor resolution
//! options.
//! \n Valid values are:
//! - \b big
//! - \b small
//! - \b tiny
uint8_t size;
} Init_Parameters;
uint8_t Sensor_Init(Init_Parameters *param);
typedef enum {
small=0,
big,
tiny
} select_size;
#endif /* ARDUCAM_FOO_H_ */
/*
* foo.c
*
*
*/
#include "foo.h"
uint8_t Sensor_Init(Init_Parameters *param)
{
switch(param->size)
{
case big:
break;
case small:
break;
case tiny:
break;
}
return 0x01;
}
/*
* foo1.h
*
* Created on: Feb 28, 2019
* Author: jnadi
*/
#ifndef FOO1_H_
#define FOO1_H_
#include "foo.h"
#include "bar.h"
#endif /* FOO1_H_ */
/*
* foo1.c
*
* Created on: Feb 28, 2019
* Author: jnadi
*/
#include "foo1.h"
void Camera_Init(){
Init_Parameters setParams; //create instance
setParams.size=big;
Sensor_Init(&setParams);
}
The physical locations of header files affect C source compilation only via the include-file search path. Headers have to be in one of the directories that are searched, and if there is more than one with the same name, then the search path order determines which is used. The association, if any, between a given header and a library is not known to the compiler, and it does not affect compilation, unless indirectly via the search path.
Your claim that
the linker complains that the struct in file a_C.h is redefined
(emphasis added) makes sense only if by "the struct" you mean an object of a structure type. The linker may complain if a variable with external linkage is defined in more than one translation unit, which will likely happen if a header contains a definition of that variable (as opposed to merely a declaration).
If instead the issue is that the structure type is redefined, then that would be diagnosed by the compiler, not the linker, and it would tend to contradict your conclusion that
Each header has the appropriate header guards
. Proper header guards are exactly what would prevent such a type redefinition issue.
1) Did I correctly identify the issue?
Not with any specificity, for sure. That there are header dependencies in both directions between headers associated with different libraries reflects poor design, but it would not inherently cause compilation or linking to fail.
2) If so [...]
N/A
3) Should I consider header guards to be limited to the scope of their
respective library?
No. Header guards are relevant at the compilation stage only, and C compilation knows nothing about libraries. All header files processed by the compiler in the course of translating a single translation unit are on equal footing. In fact, the main risk in this area is in the opposite direction: a collision of header guards.
That answers the question as posed. As for what the true nature of your build issue may be, you have not given us enough information to do more than speculate. My own speculations are already conveyed above.
Using the five files posted above and commenting out an #includes bar.h in foo.h, I believe I found the answer to my problem.
The simple answer is that header guards are not preserved once it is included into the header of another file.
When bar.h is included into another header file, its header guards are superseded by the header guards of its new host (foo.h). Thus symbol redefinition issues arise when foo1.h includes both bar.h and foo.h
Header guards only prevent a .h file from including its contents twice or more within one top-level translation unit. They are to deal with cases like this, where two or more headers need to include the same set of common definitions:
// A.h
struct A { int x, y, z; };
// B.h
#include "A.h"
struct B { struct A aye; float f, g; };
// C.h
#include "A.h"
struct C { struct A aye; long l, m; };
// main.c
#include "B.h"
#include "C.h" // error, redefinition of struct A
But each translation unit starts out with a clean macro environment, so if you include a header file in two different top-level translation units, that header's declarations are made visible (once) to each. And that's what you want. (Think about standard library headers. You wouldn't want stdio.h not to declare printf in bar.c just because there existed foo.c in the same project that also included stdio.h.)
Now, your problem is that ov5642_Sensor_Values.h defines a data object (not a type), ov5642_1280x960_RAW, and this header is included into two different top-level translation units (.c source files). Each translation unit produces an object file containing a definition of ov5642_1280x960_RAW, and you get a multiple definition error from the linker when you try to combine them.
The bug causing this problem is not that ov5642_Sensor_Values.h's header guards are ineffective. The bug is that ov5642_Sensor_Values.h should not be making any global definitions. Header files should only declare things (with rare exceptions that you shouldn't worry about until you encounter them).
To fix the bug, change ov5642_Sensor_Values.h to declare ov5642_1280x960_RAW but not define it, like this:
#ifndef ARDUCAM_OV5642_SENSOR_VALUES_H_
#define ARDUCAM_OV5642_SENSOR_VALUES_H_
#include <stdint.h>
#include "sensor_reg.h"
extern const struct sensor_reg ov5642_1280x960_RAW[];
#endif
and create a new file named ov5642_Sensor_Values.c that contains the initialized definition:
#include "ov5642_Sensor_Values.h"
extern const struct sensor_reg ov5642_1280x960_RAW[] =
{
{0x3103,0x93},
{0x3008,0x02},
{0x3017,0x7f},
.....
};
and add that file to your link.
thank you everyone especially John, Zwoi. I was up against a deadline (this was inherited code) but was able to calm myself down enough to figure out what John was saying. I moved the struct definition into a c file and used an extern pointer in the header which is similar to zwoi's declaration. I am also relieved that what I did matched zwoi's example (thank you so much!).
extern const struct sensor_reg * ov5642_1280x960_RAW;
Scoping in C is confusing as hell. I have a variable: "int qwe". This var should be visible in one or more files - f1.c in this case, but not the another f2.c .
Say i have: main.c, f1.c, f2.c, header.h
main:
call f1();
call f2();
header:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
int qwe = 1;
void f1();
void f2();
#endif // HEADER_INCLUDED
f1.c:
#include <stdio.h>
extern int qwe;
void f1(){
printf("In f1: %d\n", qwe);
}
f2.c:
#include <stdio.h>
static int qwe = 2;
void f2(){
printf("In f2: %d\n", qwe);
}
Now this gets confusing. There is definition and declaration. I have defined qwe in the header, declared it in f1.c. Is that correct? Should definition happen in header and declaration in f1.c instead? I tried the latter case, but got an error - "multiple definition of qwe". When i removed the #include directive from f1.c, it worked... It also works when i remove the extern keyword. Is extern redundant?
f2.c i guess it's ok and behaves as expected, or is it? But if i put an #include with header, it breaks. Why is that?
When should i use #include in source files? If i don't include it f1.c or f2.c it works...
Also, if i define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data. And next time that same function gets called, will have access to it, right? But the var won't be reinitialized to 0, i.e. the line where is defines won't execute. Correct?
Life stomps me :(
In the header, declare the variable. In e.g f1.c, define the variable, e.g. int qwe = 1; // at global scope.
In all files that want to see/change qwe, include the header that declares the variable. Easy-peasy.
You need to declare the variable in the header, and define it in one and only one C file.
In C, you cannot have a variable that doesn't "belong" to a given translation unit (source file). So it must be defined by exactly one translation unit in the whole program.
When you declare a variable as extern, you're telling the compiler the symbol is (possibly) external to your translation unit (c file).
It's probably also worth noting that when you try to declare a variable without extern, the variable is also defined, e.g.:
/* Declares, but does not defines external symbol 'foo' */
extern int foo;
/* Both declares AND defines bar */
int bar;
This is also different from how functions work to where the "default" syntax for declaration does NOT define a function:
/* Declare, but don't define spam */
void spam(void);
/* Declare, but don't define eggs */
extern void eggs(void);
/* Declare & define 'cheese' */
void cheese(void){ return; }
So your example should look more like this:
qwe.h:
#ifndef QWE_H
#define QWE_H
/* Declare qwe here */
extern int qwe;
#endif
f1.c:
/* DEFINE qwe here */
int qwe = 1;
f2.c:
#include "qwe.h" /*header includes the `extern int qwe` declaration */
void my_function(void)
{
/* use external symbol here! */
qwe = 10;
}
The scoping system isn't that confusing. The rule is this:
if you define something in a .c file EVERY other .c file in your program can access it (it is put in the global namespace).
if you specify static in front of its definition then only things in the SAME file can see it. This should be your default position for all functions and variables you don't want other .c files to be able to access.
It is very important to remember that extern only tells the compiler that the variable/function in question is not defined in the current file. This prevents the compiler for otherwise issuing an error because it can't find the symbol, but it has nothing to do with scoping - your .c file sees everything in the global namespace and if you have not followed the second part of the rule you will quickly find out about this at link time.
Header files similarly have nothing to do with scoping. They are just convenient places to put a bunch of extern statements and macros.
In C, you should use the header file in general to declare the data but not define the data. You don't want to define global data in a header because it will then be redundantly defined in multiple modules. The header indicates to multiple modules the existence of some data or function somewhere and what its type is, as well as common constants and macros (#defines). Outside of that, things in C are very simple. Just about anything is, technically, global unless you declare it static, keeping it scoped to the module it's defined in. The extern declarations for data in the headers and the function prototypes help the compiler know that these items are being accessed by a particular module and what the data types are for access so that the correct code can be generated.
You have:
Two functions f1 and f2 that are defined in separate modules but used in main. So these need to be declared in a header file.
A global data item qwe being used in more than one module.
A static qwe used in one module.
Assuming you want this done with one header file (you might need separate ones for f1, f2, and global data - see below), you could set up
your header as:
#ifndef MY_HEADER_H
#define MY_HEADER_H
extern int qwe;
void f1(void);
void f2(void);
#endif // MY_HEADER_H
Then in your main.c:
...
#include "my_header.h"
int qwe; // This is global and can be accessed from other modules
void main(...)
{
// call f1
// call f2
...
I just defined the global variable, qwe, in main.c arbitrarily. If you have a few globals, you can define them in their own glob_data.c module, for example, and have it's own header, glob_data.h, to declare them. Any other module that needs to access them would include the glob_data.h header so that compilation can properly be done on that module to access that data. Keeping the global data in separate headers helps with cases like you have where you have a static instance of the data versus the global, which are in conflict. You can avoid including the data header file for that global item when you want to compile with the static item.
Then in your C file, f1.c:
...system headers included...
#include "my_header.h"
void f1() {
printf("In f1: %d\n", qwe);
}
And in f2.c:
...system headers included...
#include "my_header.h" // Only if it doesn't contain `extern int qwe;`
static int qwe = 2; // This hides the global qwe and is known only
// to f2.c
void f2(){
printf("In f2: %d\n", qwe);
}
As I mentioned above, you might want to separate your function prototypes and your global data declaration in separate headers. That way, you can include only what's needed in each module and avoid conflicts, such as when you have a static int qwe; versus the global int qwe;.
I have defined qwe in the header, declared it in f1.c. Is that correct?
No, it should be the other way around. You are supposed to have a definition of a global variable in a single translation unit (that's geek speak for a .C file) but you may declare it in as many translation units as you wish. Since headers potentially get included from many translation units, declarations go in the headers.
When should i use #include in source files?
You do it when the header has anything that is needed for your translation unit to compile, with very few exceptions. Note that in some situations it may be necessary or desirable to make a forward declaration manually without including the header.
Also, if I define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data.
That is correct, the static variable inside the function will be assigned the initial value only once, and retain the value that you assign to it for as long as your program continues to run.
I saw some similar questions, but in none of them, the #ifndef HEADER_H was mentioned.
I have a header file and 2 C files:
constants.h
main.c
mylib.c
In constants.h:
#ifndef CONSTANTS_H
#define CONSTANTS_H
const int NUM_OF_ITEMS = 22;
#endif
In mylib.c:
#include "constants.h"
... code ...
In main.c:
#include "constants.h"
int main() {
... code ...
}
When I compile using the command: gcc main.c mylib.c -o main, I get the following error:
/tmp/ccl55fv3.o:(.rodata+0x0): multiple definition of `NUM_OF_ITEMS'
/tmp/ccyZhu6F.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
I mentioned #ifndef, so why it happens??
Is there anything to do except for splitting it to constants.h for declaration and constants.c for assignment?
Each translation unit (read .c source file) into which you include the header file results in a new definition of the global variable. That is why the linker objects to there being multiple definitions. Remember that #include performs text insertion of the included file. From the perspective of the compiler, each of your translation units contains distinct definitions of NUM_OF_ITEMS.
You need to define it in exactly one translation unit. You might consider adding a constants.c which contained the definition of NUM_OF_ITEMS, and leaving just a declaration in the header file.
Alternatively you could use a macro:
#define NUM_OF_ITEMS 22
Or as Jens suggests in the comment below, an enumeration constant.
Or as you yourself suggest, with static linkage so that the object is internal to each translation unit.
The include guard is required to prevent multiple-inclusion is a single translation unit during compilation. The error you have on the other hand is a linker error - because you have more than one translation unit (object file) containing the same definition.
In C one would commonly use #define to define constants as macros. This has downsides with respect to type safety. Alternatively you can do one to two things:
Localise the constant in each translation unit by declaring it static:
static const int NUM_OF_ITEMS = 22;
Declare it extern, then define in a single translation unit:
extern const int NUM_OF_ITEMS ;
constants.c:
#include constants .h
const int NUM_OF_ITEMS = 22;
Option 1 is common practice in C++ where the semantics of const are somewhat different than C, or at least more clearly defined, and unless a reference or pointer is taken to the constant, the constant will be inserted into the code as if to were a macro - i.e. there will be no distinct storage of the "variable". In C code that may or may not happen, but it will work either way but potentially marginally less efficiently.
In C (opposite to C++) constant objects have external linkake. So the both your compilation units will contain its own object with name NUM_OF_ITEMS and the linker will not know which one to use and allocate memory for it.
You could define the constant as having internal linkage that is when the object is visible only inside the compilation unit where it is used. To do that you have to use key word static
#ifndef CONSTANTS_H
#define CONSTANTS_H
static const int NUM_OF_ITEMS = 22;
#endif
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.