I am a newbie to C and C++ language, I have a question about header files in C:
a.h
#define HELLO (1)
typedef struct
{
int a;
int b;
} hello;
b.h
#include "a.h"
#define NUMBER (3)
main.c
#include "b.h"
in main.c, does struct and macro defined in a.h can be used in main.c?
Sure you can use both Struct and MACROS in the main.c
You need to be aware of the C Compilation Process, Before main.c is being compiled or linked, there is the pre-processor step:
Preprocessor:
The input to this phase is the .c File and .h Files
The preprocess process the preprocessor keywords like #define, #ifdef, #include, etc. and generate a new .pre file or .i file after the text replacement process.
The output of this phase is a C Code without any preprocessor keyword.
So the main.c will actually look like this:
#define HELLO (1)
typedef struct
{
int a;
int b;
} hello;
#define NUMBER (3)
And then replace all macros, here you don't use HELLO or NUMBER, so the pure c main file will be:
typedef struct
{
int a;
int b;
} hello;
Yes, it can be used. That is the sole purpose of #includeing of header files.
For more information, you can see the preprocessed version of code. Use
gcc -E <filename.c> //main.c, in this case
There you can see the presence of the struct and MACROS definde in the included header files.
Yes, #include directives themselves appearing in included files have their normal effect, up to an implementation-defined limit on the number of levels of inclusion. The "normal effect" is equivalent to textual interpolation -- that is, there is no separate scoping for the contents of included files -- so any declaration appearing in any directly or indirectly included file is visible to all code following the point of inclusion.
Yep, #include statements can chain multiple files together. #include literally copies and pastes the contents of one file into another, so you can think of it as a one-after-another effect.
Related
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;
This is my code. I have file1.c and file2.c. I want to call the MESSAGE from file2.c but I can't seem to do it. I am newbie in C so I really don't know what to do. I researched already but, I can't seem to find a specific answer. Thankyou.
#define MESSAGE "this is message!"
helloworld(){
printf("%s",MESSAGE);
getch();
}
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file2.c"
int main(void)
{
helloworld();
}
There are a few misconceptions you have: First of all the concept of "calling" a macro. It's not possible, even if a macro looks like a function it's not a function and macros are not actually handled by the compiler. Instead macros are part of a separate language that is handled by a preprocessor, which takes the source file and modifies it to generate a translation unit that the compiler sees. (For more information about the difference phases of "compilation" see e.g. this reference.)
The preprocessor does this by basically doing a search-replace in the input source file: When it sees a macro "invocation" it simply replaces that with the "body" of the macro. When it sees an #include directive, it preprocesses the file and then puts the content in place of the directive.
So in your code, when the preprocessor sees the macro MESSAGE it is literally replaced by "this is message!". The actual compiler doesn't see MESSAGE at all, it only sees the string literal.
Another misconception is how you use the #include directive. You should not use it to include source files. Instead you compile the source files separately (which creates object files) and then link the generated object files together with whatever libraries are needed to form the final executable.
To solve the problem of macros (and other declarations) being available to all source files, you use header files. These are like source files, but only contains declarations and macros. You then include the header file in both source files, and both source files will know about the declarations and macros available in the header file.
So in your case you should have three files: The main source file, the source file containing the function, and a header file containing the macro and the function declaration (also known as a prototype). Something like
Header file, e.g. header.h:
// First an include guard (see e.g. https://en.wikipedia.org/wiki/Include_guard)
#ifndef HEADER_H
#define HEADER_H
// Define the macro, if it needs to be used by all source files
// including this header file
#define MESSAGE "this is message!"
// Declare a function prototype so it can be used from other
// source files
void helloworld();
#endif
Main source file, e.g. main.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
int main(void)
{
// Use the macro
printf("From main, MESSAGE = %s\n", MESSAGE);
// Call the function from the other file
helloworld();
}
The other file, e.g. hello.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
void helloworld(void)
{
printf("Hello world!\n");
printf("From helloworld, MESSAGE = %s\n", MESSAGE);
}
Now, if you use a command-line compiler like gcc or clang then you can simply build it all by doing e.g.
$ gcc -Wall main.c hello.c -o myhello
That command will take the two source files, main.c and hello.c and run the preprocessor and compiler on them to generate (temporary) object files. These object files are then linked together with the standard C library to form the program myhello (that's what the option -o does, names the output file).
You can then run myhello:
$ ./myhello
From main, MESSAGE = this is message!
Hello world!
From helloworld, MESSAGE = this is message!
In your file1.c, MESSAGE is a preprocessor macro, which means the text MESSAGE will be replaced with the string "this is message!". It is not visible outside the file. This is because in C, translation units are the final inputs to the compiler, and thes translation units already have all of preprocessor macros replaced by the tokens of the corresponding argument.
If you want to have a common variable, you should declare the variable as extern in a .h header file, and then #include the file where you need to use it.
see Compiling multiple C files in a program
You have to put your #define in a .h file and include it in .c files where you want to use it.
You can write the files as below and compile the code as i mention in the following steps.
file1.h
#ifndef _FILE1_H
#define _FILE1_H
#define MESSAGE "this is message!"
extern void helloworld();
#endif
file1.c
#include "file1.h"
helloworld()
{
printf("%s",MESSAGE);
getch();
}
file2.c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file1.h"
int main(void)
{
helloworld();
return 0;
}
For compiling,
gcc -Wall file1.c file2.c -o myprog
./myprog
Here is code try this:
In File1.C
#define FILE1_C
#include "file1.h"
helloworld()
{
printf("%s",MESSAGE);
getch();
}
In File2.C
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "file1.h"
int main(void)
{
helloworld();
}
In File1.h
#ifdef FILE1_C
#define MESSAGE "this is message!"
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN helloword()
i have the following files
(its pseudo code, and i know the define, undef is ugly, but i would need it for some project)
if i compile those files and link them together - it seems to work - that in file3, file1 - MYVAL == 1
is it safe to assume this, that the preprocessor stuff is done file-by-file?
conf.h:
#define MYVAL 1
src1.c
#include "conf.h"
int maint(int argc, char ** argv) {
printf("%d", MYVAL);
}
src2.c
#include "conf.h"
void demo() {
#undef MYVAL
#define MYVAL 2
printf("%d", MYVAL);
}
src3.c
#include "conf.h"
void demo2() {
printf("%d", MYVAL);
}
regards
Preprocessing is done per translation unit before the compilation phase (so way earlier than the linkage phase). In your case the preprocessor will expand that macro in each of your .c files individually based on your inclusion of the conf.h header file.
is it safe to assume this, that the preprocessor stuff is done file-by-file?
Basically in your case yes. Each of your .c files is a distinct translation unit. (Unless they start including each other or something) They are preprocessed separately, compiled and then their objects get linked together.
When you #include "conf.h" its code is placed instead of this line. This is the preprocessor's work. So, this define sentence is placed in each file.
But if you do #define work(n) funcCall((n)) and work(5); then, it'll fail if funcCall is not defined in any of your files.
Yes, the preprocessor is used for each source file. It generates a preprocessed file from the source file and all include files that is actually passed to the C compiler.
When you #define something in a include file it gets in the preprocessed file. #defines in other source file doesn't care.
Ok, I have a pretty good understanding of how header files are to be used in C programs but I keep having this problem that I can't seem to get around. Here is the situation:
Device.c contains #include "Device.h"
Device.h contains a definition for a struct and the following...
#ifndef DEVICE_H
#define DEVICE_H
#include "SubDevice.h"
typedef struct {
subDevice * subDevice1;
subDevice * subDevice2;
} device;
#endif
SubDevice.c contains #include SubDevice.h
SubDevice.h contains the definition of the subDevice struct and the following...
#ifndef SUBDEVICE_H
#define SUBDEVICE_H
#include "Device.h"
typedef struct{
int MyInt;
double MyDouble;
}subDevice;
#endif
The problem is that I get a compiler error in Device.h in my struct definition. At the line subDevice * subDevice1; it says syntax error before subDevice.
Is the problem that I am including the header file of the other file in each file? I thought the #ifndef - #define statements would prevent that from causing a problem...
It's not a header problem. There is a problem on one typedef you have in SubDevice.h. So, do change:
typedef struct{
int MyInt;
double MyDouble;
}
To:
typedef struct{
int MyInt;
double MyDouble;
} subDevice;
Your problem should be gone.
You must put a semicolon after the declaration of a struct, and your typedef is missing the second parameter.
EDIT to reflect OP's edit
You're including DEVICE_H, which is an macro.
You need to include "device.h":
#include "device.h"
The problem is that you have a circular reference.
I guess your main file looks something like this:
#include "Subdevice.h"
#include "Device.h"
int main() {}
Because of how the C preprocessor works (and how you use the include guards), the contents of Device.h will be read before Subdevice.h, meaning that the subDevice struct has yet to be defined when you define the device struct.
Remove the #include "Device.h" from Subdevice.h and it should compile OK.
You have "typedef struct {...}" in your subdevice.h, when you should have "typedef struct {...} subDevice;"
The line "#include DEVICE_H" also looks somewhat wrong. Did you mean #include "device.h"?
What you seem to be missing is a good understanding of the compilation model used by C (and C++) compilers.
Compiling a C or C++ source file can be separated in three stages:
Preprocessing
Compiling
Linking
Preprocessing
During preprocessing, the compiler (or separate preprocessor) goes over the source file and performs macro expansion and #include replacements.
All #include directives are replaced by the contents of the referenced file.
All macro definitions are processed and where a macro invocation occurs in the text, it is substituted with the replacement text. This is a completely textual process.
After preprocessing, there are no preprocessor directives (lines starting with a #) left in the source code
Compiling
During compilation, the compiler interprets the source code according to the rules of the C (or C++) language and translates the code to object code.
Linking
During the linking phase, all object files are combined together and linked with the relevant libraries to create an executable.
The source code presented here has two problems:
The subdevice.h file contains a spurious #include DEVICE_H directive. This should be reported by the preprocessor/compiler, because DEVICE_H does not resolve to a filename in quotes or angle-brackets.
There is a missing semi-colon (;) (and a missing typedef name) at the end of the typedef in subdevice.h. As a result, the compiler tries to combine this with the next lines of code it sees (the typedef struct in device.h) and gets terribly confused. This triggers the syntax error message.
One good way of debugging your code with preprocessor errors is to gcc -E <files>, so that you can actually see what would your program look like after that preprocessor is done with it.
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.