In this tutorial we will learn about preprocessors and macros in C.
This is important.
So you can understand the process behind the C program code before compiling it.
So what are preprocessors and macros ?
How to use it?
Let's learn!
What are Preprocessors and Macros?
Before the program code is compiled into binary, the program code is processed first by the preprocessor.
The results of the process from the preprocessor are C program code that is ready to be compiled.
Why does it have to be done with a preprocessor?
So that we don't write code manually.
What does that mean?
Gini..
Take a look at this program code:
#include <stdio.h>
void main(){
printf("Hello World!\n");
}
In this program, there is a macro:
#include <stdio.h>
The function of this macro is to tell the preprocessor to insert all the code in the file stdio.h
into our program code.
So we can use the functions printf()
in it.
If there is no preprocessor , then we have to enter it manually. You can copy and paste all the contents of the code stdio.h
into our program code.
Want it like that?
Obviously not, it's tiring work.
That's why we need a preprocessor .
So..
Preprocessor is a process carried out before the program is compiled based on the given macros. The preprocessor output is program code, not a binary file. This program code will later be compiled by the compiler.
If we want to see the preprocessor results, we can use the cpp
or command gcc -E
.
Example:
cpp hello_world.c
or:
gcc -E hello_world.c
So the result is:
In the results of this preprocessor, all the existing code is stdio.h
included in the code that we write.
This is because we use macros #include <stdio.h>
.
So..
Macros are codes to provide instructions to the preprocessor.
Example of macros:
#include <stdio.h>
This macro is for giving commands to the preprocessor:
"Hi preprocessor, enter all the existing program code stdio.h
into this program code."
Apart from macros, #include
there are also other macros.
Macro Directives | Macro Functions |
---|---|
#define | Defines constants and functions |
#include | to add code to the program |
#undef | to delete macros that have been defined |
#ifdef | to check whether the macro has been defined |
#ifndef | to check whether the macro has not been defined |
#if | to create an if condition |
#else | to create an alternative to if |
#elif | to create an else if condition |
#endif | to end the if condition block |
#error | to print error messages to stderr |
#pragma | to give instructions to the compiler. |
Macro directives are symbols or words used to create or define macros.
Macro definitions can be written anywhere, either inside the main function or outside. Can be in the header file or source file.
To better understand, let's discuss it with examples.
#define and #undefine directives
As discussed in the table above...
..directive #define
and #undefine
functions to define and delete macro definitions.
Example:
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
It means:
Define constants with names SCREEN_WIDTH
with values 800
and SCREEN_HEIGH
600
.
If a macro has been defined in another file, we can redefine it by deleting the definition first with #undef
.
Example:
#undef FILE_SIZE
#define FILE_SIZE 42
Apart from defining constants, #define
we can also use directives to define functions.
Example:
#define square(sisi) ((sisi) * (sisi))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
There are two macros in the form of functions that we create, namely: square()
and MAX()
.
If we want to use this macro, we can call it like a normal function.
Example:
#include <stdio.h>
// mendefinisikan macro
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void) {
// menggunakan macro
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
If compiled and run, the output results are:
Max between 20 and 10 is 20
So it is a directive #define
and #undefine
functions to create and delete macros.
Predefined Macros
Predefined macros are macros that already exist or have been defined on our computer. We just need to use it.
Example of predefined macros:
__DATE__
contains the current date;__TIME__
contains the current time;__FILE__
contains the file name of the program code;__LINE__
contains the program line number.__STDC__
contains1
if the program was compiled to ANSI standards.
Example of use:
Create a new program file with a name predefined_macro.c
with the following contents.
#include <stdio.h>
void main() {
printf("File : %s\n", __FILE__ );
printf("Date : %s\n", __DATE__ );
printf("Time : %s\n", __TIME__ );
printf("Line : %d\n", __LINE__ );
printf("ANSI : %d\n", __STDC__ );
}
The result:
File : predefined_macro.c
Date : May 16 2022
Time : 03:36:24
Line : 8
ANSI : 1
Condition Directive
We can create conditions with macro directives, there are several directives provided to create conditions:
#if
for conditionsif
;#else
for conditionselse
;#elif
for conditionselse if
;#endif
to close or endif
;#ifdef
to check if the macro has been defined;#ifndef
to check if the macro has not been defined.
Example of use:
#include <stdio.h>
#ifndef DEBUG
#define DEBUG true
#endif
void main(){
#if defined(DEBUG)
printf("Debugging mode is on\n");
#else
printf("Debugging mode is off\n");
#endif
}
So the preprocessor results:
void main(){
printf("Debugging mode is on\n");
}
So we can choose which code will be processed based on certain conditions.
Operators on Macros
Macros have 4 operators that can be used:
1. Connection Operator
The concatenation operator uses the backslash symbol (\), its function is to connect macro definitions if there is more than one line.
Example:
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
2. Stringize Operator (#)
The stringize operator uses the fence symbol ( #
), which functions to convert macro parameters into string text.
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void) {
message_for(Petani, Kode);
return 0;
}
Maybe you will ask...
When using a macro like this:
message_for(Petani, Kode);
Why doesn't the program error, there are no quotation marks there?
Remember:
Macros are processed by the preprocessor, not the compiler. So when it is compiled the program will be able to run because preprocessing has been done beforehand.
We can check the preprocessor results with the command cpp
.
cpp kode_program.c
So the result is:
int main(void) {
printf("Petani" " and " "Kode" ": We love you!\n");
return 0;
}
3. Token Pasting Operator
The token pasting operator functions to retrieve the name of a variable or parameter given to a macro. This operator uses the double fence symbol ( ##
).
Example:
#include <stdio.h>
#define tokenpaster(n) printf ("%d", token_##n)
int main(void) {
int petani_kode = 40;
tokenpaster(petani_kode);
return 0;
}
So the preprocessor results:
int main(void) {
int petani_kode = 40;
printf ("%d", token_petani_kode);
return 0;
}
4. Operator defined()
Operators defined()
function to check the condition of a macro. Whether the macro has been defined or not. This is the same as the #ifdef
and directive #ifndef
.
Example:
#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void) {
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
So the preprocessor results:
int main(void) {
printf("Here is the message: %s\n", "You wish!");
return 0;
}
Parameters for Macros
Parameters are special variables used by macros for processing. Usually we need it when creating macros in the form of functions.
Example:
#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
void main(void) {
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
So the preprocessor results:
void main(void) {
printf("Max between 20 and 10 is %d\n", ((10) > (20) ? (10) : (20)));
return 0;
}
What is next?
Macros and preprocessing are features that help us in creating C program code. So we can create shorter program code rather than having to write all the code over and over again.
Next, please learn about header files in C to create modular programs that can be reused with macros #include
.
If you are still confused, please ask in the comments.
Post a Comment