Include header file in C curiosity - c

I have the following curiosity about the include files and how they are managed (with GCC):
Let's say I have one source file foo.c and three headers foo.h, foo_cfg.h and foo_int.h.
In foo.c:
#include "foo.h"
#include "foo_int.h"
In foo.h:
#include "foo_cfg.h"
In foo_cfg.h:
/* no inclusions */
#define FOO BAR
In foo_int.h:
/* no inclusions */
#define BAR 0U
I am wondering why the compilation succeeds. Shouldn't the foo_cfg.h file complain that it doesn't know about BAR symbol?
Furthermore I have another source file bar.c which only includes the foo.h file and still works.
Remark: this is from a project I am working on with a complex build environment of which I don't have to much details. Could it be that the build environment has an effect on this other than specifying the location for the header files?
It might be that the question is really stupid or I've overlooked something and I apologize if so.

No, it's ok.
You see, the preprocessor doesn't care if BAR is defined or not at all. It just replaces the string FOO with BAR in the source code which follows, without actually caring if it's defined at that point or not.
Next, at the actual .c file (the thing where the compilation starts) both headers are included, so the compiler sees both substitutions: FOO -> BAR and BAR -> 0U. So it successfully applies both of them.
The headers are never compiled alone, they are always compiled as a part of .c file which #includes that header. (The preprocessor just pretends that the content of the header is pasted to the place where #include is located.) So, for the preprocessor your file foo.c looks like this:
/* no inclusions */
#define FOO BAR
/* no inclusions */
#define BAR 0U
/* the rest of the file... */
/* for example: */
unsigned int i = FOO;
And the compiler after the preprocessing sees just this:
/* no inclusions */
/* no inclusions */
/* the rest of the file... */
/* for example: */
unsigned int i = 0U;
(not quite sure, maybe the preprocessor removes the comments as well.)
Edit:
Indeed, as #pmg mentions, the preprocessor replaces comments with a whitespace, so the real preprocessed text which is fed to the compiler is just
_
_
_
_
unsigned int i = 0U;
(here _ denotes a whitespace)

To extend Vlad's answer a bit:
Preprocessor macros are expanded when used, not when defined.
So when you write #define FOO BAR, all it does is remember that FOO=BAR.
When you write #define BAR 0U, it remembers that BAR=0U.
Now, when FOO is seen in the code, it's replaced with BAR, which is immediately replaced with 0U.
The order in which #define FOO and #define BAR appear in the source is unimportant. The important thing is that when FOO is seen the first time, both definitions were already done.

Related

Use a macro both in implementation and header and then undefine it

I have a macro that should be used both in my source file and header one. However I don't wan't other code linked to the final object to access that macro (more than anything else I don't want the macro to go causing unexpected errors in other files). I thought about using a macro with a long and complicated name that will be unlikely used from other code, however this solution kinda looks ugly to me. Obviously the most simple solution would be to undefine the macro in some way, however if I define the macro in the header and then undefine it – I think – I won't be able to access it anymore from the source file. What should I do?
// hi.h
#define string char *
void greet(string x);
// hi.c
#include "hi.h"
void greet(string x) {
printf("Hi!");
}
Okay, don't kill me, this was just an example, i know #define string char * is horrible.
Last minute thought: Maybe I can underfine the macro at the end of the source file, is this acceptable to do?
I guess you could conditionally "undefine" macro at the end of the header when the a magic macro is not defined. The blessed source file would have to define this macro prior to including a header.
// header.h
...
#ifndef MAGIC_MACRO
#undef string
#endif
// common source
#include "header.h"
// blessed source
#define MAGIC_MACRO
#include "header.h"
This solution will work great as long as no macro defined inside the header uses string macro.
What should I do?
Pick option 1 a macro with a long and complicated name that will be unlikely used from other code as it's the simplest and most obvious. Do not use a complicated name - just use a name so that you and other developers will know it's a private symbol, that's all.
// hi.h
// this macro is private
#define _lib_string char *
Remember about reserved words. Example: https://github.com/GNOME/glib/blob/main/glib/glib-private.h#L32 .
he most simple solution would be to undefine the macro in some way, however if I define the macro in the header and then undefine it – I think – I won't be able to access it anymore from the source file
If you go this way, you'll end up with spaghetti code, where some global state affects what you have. For example:
// hi.h
#define string char *
void greet(string x);
#ifndef FROM_HI_C
#undef string
#endif
// hi.c
#define FROM_HI_C
#include "hi.h"
void greet(string x) {
printf("Hi!");
}
Maybe I can underfine the macro at the end of the source file, is this acceptable to do?
Other files see only the header file - they are unaffected by anything in the source file.

C - Include only specific function

Alongside main.c file, I have following my_custom_data_structure.c file in my project. My my_custom_data_structure.c file contains a lot of variables, functions, etc.
I am using #include "my_custom_data_structure.c" directive in main.c.
Problem
I would like to import only single function called foo from my_custom_data_structure.c. I don't need all the variables and functions, which are declared in my_custom_data_structure.c file.
Any insights appreciated.
File structure
-
|- main.c
|- my_custom_data_structure.c
Content of my_custom_data_structure.c
#include <stdio.h>
int DELAY = 20;
int SPEED = 7;
char GRANULARITY_CHAR = 'g';
unsigned int RANGE = 3;
void foo(){
// TODO: In future, this function will print SPEED.
printf("foo works!");
}
/*
The rest of this file is filled by a lot
of code, which is not needed for main.c
*/
Content of main.c
#include <stdio.h>
#include "my_custom_data_structure.c"
int DELAY = 3;
int main(){
foo();
printf("Delay is %d", DELAY);
return 0;
}
UPDATED: Added working example
The usual way is to compile them separately. So you have your main.c, and your extra.c, and you should create a extra.h (and include it in main.c).
In this extra.h, put in declarations for anything that is to be exported from your extra.c file.
For example any functions that should be available to other files. All other functions should be declared/defined only in your extra.c as static, so that they are not available as symbols to be linked when main.c is compiled.
Normally, you don't include source files (.c) inside other source files (or inside headers). It's possible (and occasionally necessary), but it isn't usual.
Unless you've designed the my_custom_data_structure.c to allow you to specify which functions are to be compiled, you get everything in the file. For example, you could use:
#ifdef USE_FUNCTION1
void function1(void *, …)
{
…
}
#endif /* USE_FUNCTION1 */
around each function, and then arrange to
#define USE_FUNCTION1
before including the source, but that's not usually a good way of working. It's fiddly. You have to know which functions you use, and which other functions those need, and so on, and it is vulnerable to changes making the lists of USE_FUNCTIONn defines inaccurate. Of course, the source code might have blocks of code like:
#ifdef USE_FUNCTION1
#define USE_FUNCTION37
#define USE_FUNCTION92
#define USE_FUNCTION102
#endif /* USE_FUNCTION1 */
so that if you say you use function1(), it automatically compiles the other functions that are required, but maintaining those lists of definitions is fiddly too, even when the definitions are USE_MEANINGFUL_NAME instead of a number.
Create a header (my_customer_data_structure.h) declaring the functions and any types needed, and split the implementation into many files (mcds_part1.c, mcds_part2.c, …).
Compile the separate implementation files into a library (e.g. libmcds.a), and then link your program with the library. If it's a static library, only those functions that are used, directly or indirectly, will be included in the executable.

are header guards limited to the scope of their respective library?

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;

Using define in a c header file

I am just starting to learn C so hopefully this isn't a dumb question. The problem I am having is regarding header files and using #define for constants. I have read that I should use the following to prevent my header from being compiled more than once.
#ifndef NAME_OF_FILE
#define NAME_OF_FILE
.
. //my header file content
.
#endif
I want to add a constant, and I believe I would also use a #define such as,
#ifndef NAME_OF_FILE
#define NAME_OF_FILE
#define NUM_CONST 5 //the constant I want in my header file
.
.
.
#endif
How does C know that #define NAME_OF_FILE is referring to the .h file while #define NUM_CONST 5 is just a constant? Is it because of the value at the end of NUM_CONST? Or do I have this all completely wrong?
There is no essential difference between the two defines. #define NAME_OF_FILE and #define NUM_CONST 5 are the same sort of thing. They define a plaintext replacement of tokens (in the first case, the replacement is nothing).
For example you could put subsequent code:
printf("%d\n", NAME_OF_FILE NUM_CONST NAME_OF_FILE);
and after the above substitutions the code would turn in to:
printf("%d\n", 5);
which is correct. There is no "magic". The compilation step that performs these substitutions is usually known as "preprocessing".
NAME_OF_FILE does not refer to the .h file, per se, but the use of the ifndef directive achieves the goal of not compiling the same code twice.
It doesn't. NAME_OF_FILE could be anything. You could have
#ifndef PRETTY_PINK_PRINCESS
#define PRETTY_PINK_PRINCESS
/* definitions */
#endif
And it would work just as well. Using NAME_OF_FILE is just a convention because it makes it likely that it's unique.
#define IDENTIFIER defines the identifier for the sakes of #ifdef, but what it is being defined to is the empty string.
So,
#define NAME_OF_FILE
int main()
{
int x = NAME_OF_FILE;
}
would resolve to
int main()
{
int x = ;
}
So there is no "knowing" involved, just a defined-but-empty.
(That is why some style guides out there recommend #define NAME_OF_FILE NAME_OF_FILE, so that if NAME_OF_FILE happens to be used in the source, it is replaced-with-self by the preprocessor.)
For the compiler both these statement are the same type a macro
#define NAME_OF_FILE
#define NUM_CONST 5
That this construct
#ifndef NAME_OF_FILE
#define NAME_OF_FILE
.
. //my header file content
.
#endif
is doing, is that the header is processed for the first time, the marco "NAME_OF_FILE" is n ot defined, hence it get defined and the whole header file content processed. The second time the compiler comes around this, because the header was included in project more than once, is that the marco is defined now and the header file doesn't get processed again.
Again, the "c-code" is not aware, that the marco __TEST_H for example has its because the header file's name is 'test.h'. What you are reffering to is probably, that your IDE auto-generated the marco then you created the header file and that the IDE called the marco after the file for the user's convenience. Like a another one here allready said, that you can rename the marco (rename it in the whole project I mean by that) and the code would compile and generally behave exactly like before.

Why only define a macro if it's not already defined?

All across our C code base, I see every macro defined the following way:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
What is the rationale of doing these define checks instead of just defining the macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
I can't find this practice explained anywhere on the web.
This allows you to override the macros when you're compiling:
gcc -DMACRONAME=value
The definitions in the header file are used as defaults.
As I said in the comment, imagine this situation:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Will print 44.
However, if the conditional ifndef was not there, the result would be compilation warnings of MACRO redefinition and it will print 64.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
I do not know the context but this can be used to give the user the availability to override the values set by those macro definitions. If the user explicitly defines a different value for any of those macros it will be used instead of the values used here.
For instance in g++ you can use the -D flag during compilation to pass a value to a macro.
This is done so that the user of the header file can override the definitions from his/her code or from compiler's -D flag.
Any C project resides on multiple source files. When working on a single source file the checks seem to (and actually) have no point, but when working on a large C project, it's a good practice to check for existing defines before defining a constant. The idea is simple: you need the constant in that specific source file, but it may have been already defined in another.
You could think about a framework/library that gives to the user a default preset that allow the user to compile and work on it.
Those defines are spreaded in different files and the final user is advised to include it's config.h file where he can config its values.
If the user forgot some define the system can continue to work because of the preset.
Using
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
allows the user to define the value of the macro using the command line argument (in gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.
There is another important reason. It is an error to re-define a preprocessor macro differently. See this answer to another SO question. Without the #ifndef check, the compiler should produce an error if -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f is used as a command line argument in the compiler invocation.

Resources