@@ -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>
intmain(){
#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
intfunc(void){return1;}
#endif /* BAR_H */
```
And a `foo.c` file:
```c
foo.c
#include"bar.h"
#include"bar.h" // Repeated inclusion is // usually not this obvious.
intmain(void){
returnfunc();
}
```
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.