Skip to content
Snippets Groups Projects
Commit fdf86a65 authored by Mactavish's avatar Mactavish
Browse files

finish preprocessor

parent da44f22b
No related branches found
No related tags found
No related merge requests found
...@@ -472,7 +472,7 @@ A full compilation in C is depicted in the following figure: ...@@ -472,7 +472,7 @@ A full compilation in C is depicted in the following figure:
A detailed explanation can be found [here](https://www.scaler.com/topics/c/compilation-process-in-c/). A detailed explanation can be found [here](https://www.scaler.com/topics/c/compilation-process-in-c/).
## C Macros ## C Preprocessor
You often see C preprocessor macros defined to create "small functions" You often see C preprocessor macros defined to create "small functions"
...@@ -491,3 +491,71 @@ Example: ...@@ -491,3 +491,71 @@ Example:
// int y = 2; // int y = 2;
// int z = twox(y++); => z = (y++ + y++); the value of z actaully depends on the order of evaluation // int z = twox(y++); => z = (y++ + y++); the value of z actaully depends on the order of evaluation
``` ```
You can also use `#define` to define some constants:
```c
#define ARR_SIZE 100
```
### Conditional Inclusion
Frequently, you’ll need to write different code to support different implementations. You can use the preprocessing directives `#if`, `#elif`, `#else` to conditionally include source code.
Here is a simple example of using conditional inclusion:
```c
#include <stdio.h>
int main() {
#ifdef __linux__
printf("I am the Happy Penguin!\n");
#elif _WIN32
printf("Welcome to MS Windows ( I rule!).\n");
#elif __APPLE__&&__MACH__
printf("Welcome to I am cool!\n");
#else
printf("Uh! who am i?\n");
#endif
}
```
Note that the above `#ifdef` strings are standard ways of detecting the Operating System the code is being compiled on. See https://sourceforge.net/p/predef/wiki/OperatingSystems/ for further details.
### Header Guards
One problem you will face when writing header files is preventing programmers from including the same file twice in a translation unit.
Given that you can transitively include header files, you could easily include the same header file multiple times by accident.
Header guards ensure that a header file is included only once per translation unit.
Suppose we have a `bar.h` file:
```c
#ifndef BAR_H
#define BAR_H
int func(void) { return 1; }
#endif /* BAR_H */
```
And a `foo.c` file:
```c
foo.c
#include "bar.h"
#include "bar.h" // Repeated inclusion is // usually not this obvious.
int main(void) {
return func();
}
```
Using the header guard prevents the function definition of `func` being included twice.
A common practice when picking the identifier to use as a header file guard is to use the salient parts of the file path, filename, and extension, separated by an underscore and written in all capital letters. E.g. `FOO_BAR_BAZ_H` for a file located in `foo/bar/baz.h`.
There are other ways of using the preprocessor directives and macros, this [article](https://en.wikibooks.org/wiki/C_Programming/Preprocessor_directives_and_macros) and [GCC documentation](https://gcc.gnu.org/onlinedocs/cpp/) provide extensive information about them.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment