From fdf86a65cf99f157ae582d03581da7ba25c26138 Mon Sep 17 00:00:00 2001 From: Mactavish <maczhanchao@yahoo.com> Date: Mon, 24 Apr 2023 11:52:56 +0200 Subject: [PATCH] finish preprocessor --- clang.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/clang.md b/clang.md index 2e9931e..56d2dbe 100644 --- a/clang.md +++ b/clang.md @@ -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/). -## C Macros +## C Preprocessor You often see C preprocessor macros defined to create "small functions" @@ -491,3 +491,71 @@ Example: // int y = 2; // 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. -- GitLab