How Header files and macros are related? - c

just a beginner question, what's going on with #ifndef SOME_HEADER_H understandable that it is a preprocessor directive for conditional compilation, if some header is already included (i might be wrong correct me?) move on , if it's not, include it, i read at some blog the letter sentence with these words instead, if it's defined move on else #define it, well i thought we can just include a header file not define a header file , how can a header file be defined, and what's the relation here ? and the second question, the file name was foo.h and when he try to check if it's defined he does #ifndef FOO_H #define FOO_H, ok how foo.h have been translated to FOO_H , does the c mechanism know that he's talking about that specific file or does he done something before-word? thank's for your time!

There is no such thing as translating foo.h as FOO_H, nor such thing as "defining that a .h has already been included". Using preprocessor variables is just the standard way C developers ensure that .h are not included twice.
In C preprocessor, you can use things such as #if, #else and #endif in order to make logic. You can also #define variables, to store information. You can also use the function defined(...) to check if a C-preprocessor variable is already defined. The #ifdef MY_VARIABLE directive is just a shorthand for #if defined(MY_VARIABLE), and #ifndef is just the opposite of that.
On the other hand, you don't want a .h to be included twice, there are several ways to do this, but the standard way is:
/* Check if my variable has already been declared */
#ifndef MY_aWeSoMe_VARIBLE
/* If we are in here, it mean that it is not */
/* So let's declare it */
#define MY_aWeSoMe_VARIBLE
/* You can write some more code here, like your .h stuff */
/* And of course, it's time to close the if */
#endif /* This closes the MY_aWeSoMe_VARIABLE ifndef */
The 1st time your complier will include the .h, MY_aWeSoMe_VARIABLE won't be defined yet, so preprocessor will get inside the if, define the variable, include all the .h's code. If your compiler comes to include the .h a 2nd or more time, the variable will already be defined, so the preprocessor won't get inside the if. Since all the .h's content is inside the if, it won't do anything.
Since naming a variable MY_aWeSoMe_VARIABLE is pretty stupid, people tend to name it like MY_FILE_NAME, or MY_FILE_NAME_H, but this is not mandatory, practices actually vary from one dev to another.

What you have here is a header guard:
File: some_header.h
#ifndef SOME_HEADER_H // if SOME_HEADER_H is not defined, enter the
// #ifndef ... #endif block
#define SOME_HEADER_H // and define SOME_HEADER_H
struct foo {
int x;
};
#endif
This protects the header from being included more than once in the same translation unit and thereby trying to define the same entities more than once. The macro SOME_HEADER_H will stay defined until the translation unit is done so no matter how many times this header is included in the translation unit (implicitly via other header files) its contents will only be parsed once for that translation unit.
You can now do this:
File: some_other_header.h
#ifndef SOME_OTHER_HEADER_H
#define SOME_OTHER_HEADER_H
#include "some_header.h" // this header uses some_header.h
struct bar {
struct foo x;
};
#endif
And a program can now include both header files without getting an error like redefinition of 'foo'.
File: main.cpp
#include "some_header.h"
#include "some_other_header.h"
int main() {}
A non-standard but quite popular alternative to the classic header guards shown above is #pragma once which does the same thing (if your preprocessor supports it):
File: some_header.h
#pragma once
// no need for a named macro or #endif
struct foo { ... };

Related

Typedef is declared in other header, is included in necessary files, however produced: Error[Pe020]: identifier "" is undefined. Why?

Let's say I have the project in C in IAR, and I'm working with these 4 files. I have a header for defines, and another header for extern functions. I also have two .c files, one for main, and one for functions, as shown below.
First header file: header1.h
#ifndef __HEADER1_H
#define __HEADER1_H
#include "header2.h"
#include "otherheader.h"
// bunch of 'define' here
typedef uint8_t macAddr[8];
#endif
Another header file: header2.h
#ifndef __HEADER2_H
#define __HEADER2_H
//other extern functions here
extern void getMAC(macAddr deviceAddr);
#endif
main.c file here:
#include "header1.h"
void main ()
{
macAddr dev1Address = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
getMAC(dev1Address);
}
function.c file here:
#include "header1.h"
void getMAC(macAddr deviceAddr)
{
uint8_t transmit[8];
for (int i = 0; i<8; i++)
transmit[i] = deviceAddr[i];
}
The error reported is this:
Error[Pe020]: identifier "macAddr" is undefined
I'm having a little trouble understanding why this does not work. The first header (where macAddr is defined) includes the second header (where getMac() function is declared), and the first header is included in main.c as well as function.c. As far as I understand, there is no circular includes (as other questions suggested... correct me if I'm wrong, and show me how)
Problem is that header1.h includes header2.h, but header2.h requires macAddr which is not yet defined.
Rule of thumb is that each file should include only the files it needs. Thus:
header1.h has a single typedef. It should only include stdint.h.
header2.h needs macAddr to work, thus it should include header1.h.
main.c uses getMAC, so it should include header2.h. header1.h is already included, so no need to include it.
function.c strictly only needs header1.h, but it's good practice to make sure that function declaration and definition match, so it should include header2.h instead.
It seems like header1.h is used as a monolith header that is used to include everything (It's hard to be sure because your example has so few files). This is a very bad practice. It can increase compilation times, and makes refactoring hard since dependencies are difficult to track.
Ideally each header should only have single well defined responsibility. It's not always possible, but it's a good goal.
Circular includes are not a huge issue as long as you use header guards as you have, and not include everything everywhere unless it's needed. Sometimes you might need to add extra forward declarations, but that's about it.
Here's some additional notes:
As user3629249 and others noted, you really shouldn't declare symbols starting with _ underscore. These are reserved for C standard or compiler use.
I don't recommend using typedef on arrays (or pointers). Arrays decay to pointer in some cases without telling you, so when using typedef this is hidden from user and can cause bugs with careless use. I would wrap it struct instead:
typedef struct { uint8_t address[8]; } MAC_T;

Multiple Include Optimization

I'm trying to understand how multiple-include optimization works with gcc.
Lately, I've been reading a lot code that has include guards for standard header files like so
#ifndef _STDIO_H_
#include <stdio.h>
#endif
and I'm trying to figure out if this construct has any benefits.
Here's an example I wrote to understand this a little better.
header1.h
#ifndef _HDR_H_
#define _HDR_H_
#define A (32)
#endif
header2.h
#ifndef _HDR_H_
#define _HDR_H_
#define A (64)
#endif
hdr.c
#include <stdio.h>
#include "header1.h"
#include "header2.h"
int main()
{
printf("%d\n", A);
return 0;
}
Note that both header1.h and header2.h use the same include guard. As expected this program outputs the value of A defined in header1.h; header2.h is skipped since it uses the same include guard.
Here's what I'm trying to understand
At what point when parsing header2.h does the preprocessor skip this file? My understanding is that it skips this file immediately after the #if directive on line 1, i.e. it does not have to wait for the matching #endif. Is this correct?
What can I add to the example above to demonstrate how this works?
EDIT: Thanks everyone for the answers. This is starting to make more sense now. A follow up question. The page linked to on the first line of this post has the following text
The preprocessor notices such header files, so that if the header file
appears in a subsequent #include directive and FOO is defined, then it
is ignored and it doesn't preprocess or even re-open the file a second
time. This is referred to as the multiple include optimization.
If I understand this correctly, this means that any header file is read only once even it is included multiple times for a given compile process. And so, additional include guards in application code or header file provide no benefit.
At what point when parsing header2.h does the preprocessor skip this file?
As #Sean says, header2.h will never be skipped, but the content between the ifndef ... endif will be ignored in this case.
What can I add to the example above to demonstrate how this works?
Add something (for example, a #define B 123) after the #endif in header2.h. Now try to access it in the main. It will be accessible.
Now, try to add it before the #endif. You'll see, that it's not accessible in the `main.
At what point when parsing header2.h does the preprocessor skip this file?
The file is not skipped.
My understanding is that it skips this file immediately after the #if directive on line 1, i.e. it does not have to wait for the matching #endif. Is this correct?
Yes and No. Some compilers identify the sentry macro when it parses the first header file and if it finds it in a second file, it will immediately stop parsing. Other compilers will parse the header again (looking for the matching #endif).
What can I add to the example above to demonstrate how this works?
Add a print message inside and outside the sentry macro
#ifdef _HEADER_INCLUDED
#define _HEADER_INCLUDED
...
#pragma message ("inside sentry in " __FILE__ "\n")
#endif //#ifdef _HEADER_INCLUDED
#pragma message ("outside sentry in " __FILE__ "\n")
Relevant material:
You can use #pragma once instead of the sentry macro. Faster compilation since very little of the file is parsed. No worries about macro name collisions.
You can wrap the includes if checks to sentry macro so the header file isn't loaded again. This is usually used in library headers that include multiple headers many times. Can significantly speed up compilation at the expense of ugly code:
#ifndef __LIST_H_
#include "list.h"
#endif
The pre-processor will never skip header2.h. It will always include it, and when expanding it will ignore the stuff in the #ifndef block.
In your example A will be 32, as the #define in herader2.h will never be reached. If it was reached you'd get some sort of "macro redefinition error" as you'd have multiple #defines for "A". To fix this you#d need to #undef A.
Most compilers support the #pragma once directive these days to save you having to write include guards in header files.
The preprocessor starts blocking all input that follows a false #if[[n]def] to go to through subsequent compiler steps.
The preprocessor does however continues reading the input, to keep track of nesting depth of all those conditional compilation #-directives.
When it finds the matching #endif, of where it started blocking input, it simply stops blocking.
If I understand this correctly, this means that any header file is read only once even it is included multiple times for a given compile process. And so, additional include guards in application code or header file provide no benefit.
No gcc compiler only does this optimization for files that it knows to be safe following the rules:
There must be no tokens outside the controlling #if-#endif pair, but whitespace and comments are permitted.
There must be no directives outside the controlling directive pair, but the null directive (a line containing nothing other than a single ‘#’ and possibly whitespace) is permitted.
The opening directive must be of the form
#ifndef FOO
or
#if !defined FOO [equivalently, #if !defined(FOO)]

Including header file causes conflicting types

So I have this struct in a header file, called it h1.h
typedef struct{
int a;
int b;
special_t test;
} randomDataType
So I include the header file that contains the declaration of special_t. None of the functions in either header file are named the same, and I don't see how circular dependencies could come into play since the functions declared in the second header file are only ever accessed through the functions declared in h1.h
Yet I have a 'previous declaration of __' error for everything in the other header. Why is this?
It sounds like you do not have multiple inclusion guards on your header files. Except in very rare cases which you will know when you get to them, C header files should be written like this:
/* This is h1.h.
This is its license.
This is what you will find here. */
#ifndef H1_H__
#define H1_H__
all declarations go here
#endif /* h1.h */
There should not be anything outside the #ifndef ... #endif block except for comments, and you need to pick the macro name so that it won't conflict with any other header -- assume that all C header files have this construct in them, or something very like it.
What this does is allow you to #include "h1.h" as many times as you like; the compiler will only process its contents once. Many compilers recognize this construct and won't even open the file again (as long as the macro is still defined). Thus, you can safely include headers from other headers (that might need only a few of the declarations) without worrying about what any other file has done.

What is the conventional way of defining macros in main.c that are needed in other header files?

For example I have a can.h header file that contains
#ifdef MC
extern int speed;
// many more variables and function prototypes
#endif
EDIT: I would want an option for the user to define MC that enables such variable and function prototypes. It is to be defined in C main alongside include directives (e.g. #define MC) however, other header files cannot link to main.c. Instead, i ended up defining such macros in can.h header itself. All i can think is writing a main.h too where can.h will include main.h. are there other ways to go around this problem?
It's not entirely clear to me what you are trying to do, but perhaps you want this:
/* in file can.h */
extern int speed;
and then
/* in file main.c */
#include "can.h"
int speed;
The header can.h just declares the existence of speed so that other modules can refer to it as an external symbol. The storage for this object is then allocated in main.c, when you write the the definition of speed.
You can either create a configuration header that has all the macros that you want defined and #include it in every header, or you can define configuration macros on the command line.
Use #include - Then you get those bits that you require
Inclusion is simply file content insertion by the preprocessor, anything declared or defined prior to inclusion will be defined in the include file. So:
#define MC
#include "can.h"
While that achieves what you have asked, I would not necessarily recommend it however, and might question the design.
You can have such macro added at your project level.
Such macro are also known as Preprocessor definitions. Visual studio provides such definition in project settings/configurations..
So you can have it added there and compile the solution for including mentioned declarations or remove it if you don't want to include it.
Adding the screen shot.

#include <> files in different files

If I have a several header files :lets say 1.h, 2.h, 3.h.
Let's say the all three of the header files have #include <stdlib.h> and one of the include files in them.
When I have to use all 3 header files in a C file main.c,
it will have 3 copies of #include <stdlib.h> after the preprocessor.
How does the compiler handle this kind of conflict?
Is this an error or does this create any overhead?
If there are no header guards, what will happen?
Most C headers include are wrapped as follows:
#ifndef FOO_H
#define FOO_H
/* Header contents here */
#endif
The first time the preprocessor scans this, it will include the contents of the header because FOO_H is undefined; however, it also defines FOO_H preventing the header contents from being added a second time.
There is a small performance impact of having a header included multiple times: the preprocessor has to go to disk and read the header each time. This can be mitigated by adding guards in your C file to include:
#ifndef FOO_H
#include <foo.h>
#endif
This stuff is discussed in great detail in Large-Scale C++ Software Design (an excellent book).
This is usually solved with preprocessor statements:
#ifndef __STDLIB_H
#include <stdlib.h>
#define __STDLIB_H
#endif
Although I never saw it for common header files like stdlib.h, so it might just be necessary for your own header files.
The preprocessor will include all three copies, but header guards will prevent all but the first copy from being parsed.
Header guards will tell the preprocessor to convert subsequent copies of that header file to effectively nothing.
Response to edit:
Standard library headers will have the header guards. It would be very unusual and incorrect for them to not have the guards.
Similarly, it is your responsibility to use header guards on your own headers.
If header guards are missing, hypothetically, you will get a variety of errors relating to duplicate definitions.
Another point: You can redeclare a function (or extern variable) a bazillion times and the compiler will accept it:
int printf(const char*, ...);
int printf(const char*, ...);
is perfectly legal and has a small compilation overhead but no runtime overhead.
That's what happens when an unguarded include file is included more than once.
Note that it is not true for everything in an include file. You can't redeclare an enum, for example.
This is done by one of the two popular techniques, both of which are under stdlib's responsibility.
One is defining a unique constant and checking for it, to #ifdef out all the contents of the file if it is already defined.
Another is microsoft-specific #pragma once, that has an advantage of not having to even read the from the hard drive if it was already included (by remembering the exact path)
You must also do the same in all header files you produce. Or, headers that include yours will have a problem.
As far a I know regular include simply throws in the contents of another file. The standard library stdlib.h urely utilizes the code guards: http://en.wikipedia.org/wiki/Include_guard, so you end up including only one copy. However, you can break it (do try it!) if you do: #include A, #undef A_GUARD, #include A again.
Now ... why do you include a .h inside another .h? This can be ok, at least in C++, but it is best avoided. You can use forward declarations for that: http://en.wikipedia.org/wiki/Forward_declaration
Using those works for as long as your code does not need to know the size of an imported structure right in the header. You might want to turn some function arguments by value into the ones by reference / pointer to solve this issue.
Also, always utilize the include guards or #pragma once for your own header files!
As others have said, for standard library headers, the system must ensure that the effect of a header being included more than once is the same as the header being included once (they must be idempotent). An exception to that rule is assert.h, the effect of which can change depending upon whether NDEBUG is defined or not. To quote the C standard:
Standard headers may be included in any order; each may be included more than once in
a given scope, with no effect different from being included only once, except that the
effect of including <assert.h> depends on the definition of NDEBUG.
How this is done depends upon the compiler/library. A compiler system may know the names of all the standard headers, and thus not process them a second time (except assert.h as mentioned above). Or, a standard header may include compiler-specific magic (mostly #pragma statements), or "include guards".
But the effect of including any other header more than once need not be same, and then it is up to the header-writer to make sure there is no conflict.
For example, given a header:
int a;
including it twice will result in two definitions of a. This is a Bad Thing.
The easiest way to avoid conflict like this is to use include guards as defined above:
#ifndef H_HEADER_NAME_
#define H_HEADER_NAME_
/* header contents */
#endif
This works for all the compilers, and doesn't rely of compiler-specific #pragmas. (Even with the above, it is a bad idea to define variables in a header file.)
Of course, in your code, you should ensure that the macro name for include guard satisfies this:
It doesn't start with E followed by an uppercase character,
It doesn't start with PRI followed by a lowercase character or X,
It doesn't start with LC_ followed by an uppercase character,
It doesn't start with SIG/SIG_ followed by an uppercase character,
..etc. (That is why I prefer the form H_NAME_.)
As a perverse example, if you want your users guessing about certain buffer sizes, you can have a header like this (warning: don't do this, it's supposed to be a joke).
#ifndef SZ
#define SZ 1024
#else
#if SZ == 1024
#undef SZ
#define SZ 128
#else
#error "You can include me no more than two times!"
#endif
#endif

Resources