Preprocessor macros in C were introduced as part of the language to ensure portability, readability, and convenience in configuring source code. With directives such as #define, #ifdef, and #ifndef, you can create conditional code sections, declare constants, and include external files (#include).
Background:
Preprocessor directives were introduced to simplify the adaptation of source code to different systems and compilers, as well as to automate repetitive tasks.
Problem:
Without a preprocessor, it was impossible to abstract from platform differences, repeat code fragments, or protect against multiple inclusions of header files. Furthermore, care must be taken as macros are not typed and do not have a scope.
Solution:
Using preprocessor macros to declare constants, inline functions, conditional compilation, and to prevent multiple inclusions of header files.
Code example:
#ifndef MY_HEADER_H #define MY_HEADER_H #define MAX_SIZE 100 #ifdef DEBUG #define LOG(x) printf("%s\n", x) #else #define LOG(x) #endif #endif /* MY_HEADER_H */
Key features:
What happens if you forget the include guard in a header file?
The header file may be included in one .c file multiple times (implicitly through other .h files), leading to redefinition errors.
What is the difference between a #define macro and an inline function declaration?
#define simply replaces text without checking types and syntax correctness, while an inline function is a regular function that is checked by the compiler during type analysis.
Can macros have side effects?
Yes, if a macro is defined carelessly, the passed expressions may be evaluated multiple times. For example:
#define SQUARE(x) (x) * (x) int a = SQUARE(++i); // ++i will execute TWICE!
Using a macro without parentheses and with an expression that creates side effects:
#define DOUBLE(x) x + x int result = DOUBLE(1+2); // expected result is not 6, but 1+2+1+2=6? No, it evaluates to 1+2+1+2. // In reality, it will be 1 + 2 + 1 + 2 = 6, but if DOUBLE(++i), then ++i will apply twice.
Pros:
Cons:
Defining a macro with parentheses and using it for simple constants:
#define DOUBLE(x) ((x) + (x)) #define BUFFER_SIZE 1024
Pros:
Cons: