#ifdef #else #endif macro question - c

I am new to C, and I am maintaining someones code. I came across this in the header file. I can understand that if the source is compiled on the windows it will enter the if statement else if the code is compiled on a linux it will enter the else statement. Correct me if I am wrong.
However, the question is why is # (hash) used in front of all the include headers?
Many thanks for any suggestions,
#ifdef WIN32
# include <conio.h>
# include <process.h>
# include <stdlib.h>
# include <string.h>
#else
# include <unistd.h>
# include <termio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
#endif

The hash (#) indicates a preprocessor directive. The preprocessor runs over the code before compilation and does things depending on all the lines beginning with "#". The "#include filename.h" directive essentially copies all the contents of filename.h and pastes it where the "#include filename.h" line was.

#include is the way you include files in C.
You might be confused by the spaces between the # and the include.
But they don't matter. These lines are still #include.

Because "#include" is the syntax for tell the preprocessor to include a header. The spaces after the pound are just there for formatting and are not strictly necessary.

The # lines are actually handled not by the C compiler itself, but by a preprocessor that runs as an early stage in the compilation pipeline. The "#" is how it knows which lines it is responsible for.
That same preprocessor can be used in other contexts as well.
The preprocessor can not only do evaluation of expression, as in the #if and #ifdef clauses, but it can also open other files and insert them using #include and even do text substitution using #define clauses.
More information can be found in the Wikipedia entry on the C preprocessor.
#include is different from, say, the VB.Net Imports statement or the C# using statement. Those make references to other classes, but #include actually inserts the text of the included file at that location in the source file. And it can act recursively, so that included files may themselves #include still others.

The #include directive tells the preprocessor to treat the contents of a specified file as if those contents had appeared in the source program at the point where the directive appears.
http://msdn.microsoft.com/en-us/library/36k2cdd4(VS.80).aspx

include, ifdef, etc. Are all preprocessor directives, so they must have the pound (or hash) character in front of them. The coder who wrote this code simply lined up all of those # characters on the left side to make to code look cleaner (in his opinion).
cplusplus.com has a good overview of preprocessor directives.

Related

What happens when preprocessor lines are processed by the preprocessor? - the '.i' file

I am using Gnu cc compiler of Gcc to compile my C programs. Consider a program,
#include <stdio.h>
int main(){
return 0;
}
Now, when I pre-process the above code, using
cpp sample.c > sample.i
I get a lot of contents in sample.i which I haven't included. Say, 'stdio.h' file is preprocessed. If that is the case,
Question 1:
Why are there so many lines in my preprocessed file? I haven't used any of the standard library functions nor Macros.
Question 2:
Can anyone explain what exactly happens when the preprocessor proccess the C file.(The contents that I got in my '*.i' file)
Compiler: gcc
OS: Ubuntu
Thanks
Why are there so many lines in my preprocessed file? I haven't used any of the standard library functions nor Macros.
Preprocessing is just one part of the compilation process. It's more or less a simple textual replacement and nothing more complex is involved at the preprocessing stage. The preprocessor does not know or care whether you have used any standard functions in your code program or not. An optimizer (as part of the compilation process) might
"remove" parts that are not needed. But the preprocessor doesn't do that.
It'll do preprocessing of all the header files you have included and other header files included via your header files and so on.
Can anyone explain what exactly happens when the preprocessor process the C file.(The contents that I got in my '*.i' file)
The preprocessing involves quite a few tasks: macro replacement, conditional compilation, stringification, string concatenation etc.
You can read more about cpp in detail here: https://gcc.gnu.org/onlinedocs/cpp/
the preprocessor command #include "aFile.h" will put the hole content from aFile.h into your cpp file. And that exactly to the place, where the preprocessor directives stands. That is the reason why you can use the in aFile.h defined functions.
if you are interest to learn more about the preprocessor, there is a very good (and short) guidance on cplusplus.com
The preprocessor does text substitution. The net effect of #include <stdio.h> is to replace the #include <stdio.h> line with the contents of <stdio.h>.
Practically, <stdio.h> contains several declarations of various functions (e.g. fprintf(), fscanf()), declarations of variables (e.g. stdout, stdin), and some macro definitions (which, when used in later code, cause text substitution).
The preprocessor is specified as a phase of compilation, which takes source code as input, substitutes text as required (e.g. the #include as I have described, macro expansions, etc), and outputs the resultant source code. That output is what you are directing into sample.i
The output of the preprocessor is then input to a later phase of compilation, which actually understands declarations, definitions, statements, etc.
The phases of compilation are sequential - they occur one after the other, not all at once. So the later phase of compilation feeds no information whatsoever back to the preprocessor. It is the later phase of compilation that detects if declarations etc are used. But, since it cannot feed such information back to the preprocessor (and the preprocessor is an ignorant program that couldn't use such information anyway) the preprocessor cannot know that declarations are unused, and filter them out.
1) You may not use them, but you have included them in line 1
#include <stdio.h>
That's where what you see come from. Try to remove it to see the difference.
2) The preprocessor read your C file and processed all preprocessor directives that you have declared. All Preprocessor directives start with a '#' symbol. The '#include' will replace this line by the content of the given file. You also have the classical '#ifndef' and '#define' directive. The latter is equal to 'if' statement which allow you to activate a part of a code only if a symbol is defined
#ifndef _SOME_SYMBOL_
#define _SOME_SYMBOL_
#ifndef WIN32
#include <some_file.h>
#else
#include <some_other_file.h>
#endif
int main() { return 0;}
#endif //endof _SOME_SYMBOL_
#ifndef _SOME_SYMBOL_
#define _SOME_SYMBOL_
// this second function is ignored
int main() { return 0;}
#endif //endof _SOME_SYMBOL_
When the preprocessor reads the above file, the symbol "_SOME_SYMBOL_" is unknown, so the preprocessor initializes it. Next it includes the file whether or not it knows of WIN32. Usually this kind of symbol is passed trough command line. So part of your code is dynamically activated or deactivated.
The preprocessor will output this
void some_other_function_from_some_other_file(){}
int main() { return 0;}

Is there a clean portable way to "build" include-file names

Many C projects have mile-long lists of "include" directories, and C source files often include tricky relative paths in their include directives. This can sometimes lead to ambiguities when files in different directories (and possibly serving different purposes) have the same name, and can also lead to slow compilation since the compiler has to search many places for each #include file.
A conceptually cleaner approach would be to have for each project a designated #include search directory which contained a filepaths.h file that would define macros for all the directories where include files resided, so that code anywhere in the project could then say something like
#include IO_INCLUDES(serialports.h)
#include IO_INCLUDES(timer.h)
#include FILESYS_INCLUDES(filesystem.h)
#include FILESYS_INCLUDES(dirhandling.h)
possibly with quotes; possibly without. If C defined #include "string1" "string2" as equivalent to #include "string1string2", handling include-files paths in such fashion would be easy, but it doesn't (in that case, the macros could accept arguments enclosed in quotes, and the macros could simply prepend suitable path names, also in quotes), but it doesn't.
An approach which almost works is to define things like:
... within a filepaths.h file
#define QUOTE(x) #x
#define MQUOTE(x) QUOTE(x)
#define DUP(x) x
#define MAKENAME(file,path) MQUOTE(DUP(file)DUP(path))
#define IO_INCLUDES(name) MAKENAME(d:/shared_libraries/io,name)
#define FILESYS_INCLUDES(name) MAKENAME(d:/shared_libraries/filesys,name)
... within an individual C file
#include IO_INCLUDES(serialport.h)
GCC seems to accept this, with proper desired semantics, if no path name component is recognized specially by the preprocessor. Requiring that project files must be stored in paths whose names don't match any macros or anything else the preprocessor might recognize doesn't seem reasonable, however.
Is there any safe and portable way to allow a filepaths.h file to indicate the directories from which files should be retrieved? The fact that the preprocessor accepts macros within #include directives would suggest that some such functionality was intended, but I can't figure out any way to make it work safely. Is there one?
There is not. According to 6.10.2 paragraph 4 of C99,
"The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined", so any attempt to do this will be nonportable.
You essentially have two options. If you really want to have no restrictions on directory names at all, then you'll need to use a separate program to do this part of the preprocessing. Make itself would probably be sufficient; something like m4 would be overkill here.
The other option, and the one I recommend, is to just establish a basic naming convention. Make all your macro names be ALL-CAPS and all your directory names be not in all caps. Then include your own headers before any others so you don't need to worry about what other people named their macros, and the problem vanishes.

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)]

How to understand a #include inside a enum definition?

How do I interpret this C code:
typedef enum {
#include <test.h>
enum1,
enum2,
…
} test_enum;
test.h includes many macros. How to understand this?
Does means that the definitions of the enum needs the macros defined inside the header file?
Can #include appear anywhere?
An #include statement may appear on any line. It is most often used to include entire declarations. However, it can be used to insert any text.
It may be that test.h contains a list of names to be declared inside the enum. It may also contain preprocessor statements, such as macro definitions or #if … #endif statements.
You would have to show the contents of test.h for further help understanding it.
#include and #define are pre processor directives not actual code.
You can put them anywhere (except as part of a literal string) - some compilers are more fussy than others (i.e. the # has to be in column 0).
The Preprocessor expands these out as required, and that is what the compiler sees. As to what it means in your case, depends on the content of test.h
There is normally a compiler option to see your code with all the preprocessor stuff expanded (used to be -e or -E on gcc I think)
The #include directive causes the contents of the included file to be placed exactly at the point of the #include directive. The resulting code is what it is once that expansion has taken place, and can be any valid language construct.
If the included file contains:
enum_a,
enum_b,
enum_c,
Then after inclusion, your code would look like:
typedef enum {
enum_a,
enum_b,
enum_c,
enum1,
enum2,
…
} test_enum;
Which is a valid construct.
A #include directive can appear anywhere. See this.
Pre-processor statements can occur anywhere and are simple textual substitutions. Whether or not the processed code is valid C code is checked by the compiler, not the pre-processor.
Depending on your compiler you can review the changes done by the pre-processor.
For gcc, this would be the -E flag, so by compiling your source code with
gcc -E in.c
you can see which changes code is contained in the enum declaration after inserting test.h and
processing it.

What does #include actually do?

In C (or a language based on C), one can happily use this statement:
#include "hello.h";
And voila, every function and variable in hello.h is automagically usable.
But what does it actually do? I looked through compiler docs and tutorials and spent some time searching online, but the only impression I could form about the magical #include command is that it "copy pastes" the contents of hello.h instead of that line. There's gotta be more than that.
Logically, that copy/paste is exactly what happens. I'm afraid there isn't any more to it. You don't need the ;, though.
Your specific example is covered by the spec, section 6.10.2 Source file inclusion, paragraph 3:
A preprocessing directive of the form
# include "q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters.
That (copy/paste) is exactly what #include "header.h" does.
Note that it will be different for #include <header.h> or when the compiler can't find the file "header.h" and it tries to #include <header.h> instead.
Not really, no. The compiler saves the original file descriptor on a stack and opens the #included file; when it reaches the end of that file, it closes it and pops back to the original file descriptor. That way, it can nest #included files almost arbitrarily.
The # include statement "grabs the attention" of the pre-processor (the process that occurs before your program is actually compiled) and "tells" the pre-processor to include whatever follows the # include statement.
While the pre-processor can be told to do quite a bit, in this instance it's being asked to recognize a header file (which is denoted with a .h following the name of that header, indicating that it's a header).
Now, a header is a file containing C declarations and definitions of functions not explicitly defined in your code. What does this mean? Well, if you want to use a function or define a special type of variable, and you know that these functions/definition are defined elsewhere (say, the standard library), you can just include (# include) the header that you know contains what you need. Otherwise, every time you wanted to use a print function (like in your case), you'd have to recreate the print function.
If its not explicitly defined in your code and you don't #include the header file with the function you're using, your compiler will complain saying something like: "Hey! I don't see where this function is defined, so I don't know what to with this undefined function in your code!".
It's part of the preprocessor. Have a look at http://en.wikipedia.org/wiki/C_preprocessor#Including_files. And yes, it's just copy and paste.
This is a nice link to answer this question.
http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
Usually #include and #include "path-name" just differs in the order of the search of the pre processor

Resources