We will discuss the concept of Macros. A Macro is a name given to a piece of code or to a value. Whenever the macro is used in the code, it is replaced by its value at the very first stage (preprocessing stage) of compilation process. They are defined using '#define' directive. For example, Consider the following piece of code: Code: #include<stdio.h> #define MYMACRO1 //define first macro #define MYMACRO2 // define second macro int main(void) { #ifdef MYMACRO1 // test whether MYMACRO1 is defined? printf("\n MYMACRO1 Defined \n"); #endif #ifdef MYMACRO2 // test whether MYMACRO1 is defined? printf("\n MYMACRO2 Defined \n"); #endif return 0; } In the above piece of code, we defined two macros : MYMACRO1 MYMACRO2 And in the main() function we tested whether these two macros are defined? If yes, then we printed a statement using printf(). Why are Macros required This question may arise in your mind that why do we require macros? What purpose they can serve? Well, I'll give you a very simple situation. Suppose you want to write a code in which you have lots of debugging statements, say something like this : Code: #include<stdio.h> #include<signal.h> #include<unistd.h> #include<stdlib.h> int flag; char *s; void func() { printf("\n Calling realloc \n"); char *ptr = realloc(s,10); printf("\n realloc call done, freeing global ptr\n"); free(s); if(flag == 0) { unsigned int i = 0; for(;i< (0xFFFFFFFF);i++); } if(ptr) { *ptr = 'a'; printf("\n Updating global ptr\n"); s = ptr; } } void sig_handler(int signo) { printf("\n Inside sig_handler\n"); flag = 1; if (signo == SIGUSR1) printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else printf("ERR : received signal %d\n", signo); func(); printf("\n Done with sig_handler()\n"); } int main(void) { printf("\n Inside main() \n"); if (signal(SIGUSR1, sig_handler) == SIG_ERR) printf("\ncan't catch SIGUSR1\n"); if (signal(SIGUSR2, sig_handler) == SIG_ERR) printf("\ncan't catch SIGUSR2\n"); int i = 0; while(i<10) // Simulate a dummy wait { func(); i++; } free(s); printf("\n Exiting main() \n"); return 0; } I was using this code earlier some day to write an article on Non-reentrant functions to explain how they can cause damage if used from within signal handlers (please don't run this code because it will crash. It was coded this way to explain the reason of crash). Anyways, I used a lot of printf calls as debugging statements. Now, suppose a need arises where I just want to run my program without any debugging statements. What would I do? Will I comment all the printfs?? Will I remove all the printfs?? Well removing a printf completely from code is not a wise decision as you can again require these debugging statements. Commenting them one by one would be a tedious task as number of debugging statements grow. OK, for those coding freaks who say commenting is still feasible by writing a separate program that can treat this program as a text file and comment printf statements. What will you do if : I want three level of debugging statements in code. (data flow, stack info, All) This mean, if I turn on one level then printf corresponding to only that level are seen on stdout. OK, now give up Commenting the code is not a elegant solution in this case. The answer to above situation is using MACROS. I'll rewrite the above code here with macros : Code: #include<stdio.h> #include<signal.h> #include<unistd.h> #include<stdlib.h> int flag; char *s; //#define DBG_LVL1 //#define DBG_LVL2 //#define DBG_LVL3 void func() { #ifdef DBG_LVL3 printf("\n Calling realloc \n"); #endif char *ptr = realloc(s,10); #ifdef DBG_LVL3 printf("\n realloc call done, freeing global ptr\n"); #endif free(s); if(flag == 0) { unsigned int i = 0; for(;i< (0xFFFFFFFF);i++); } if(ptr) { *ptr = 'a'; #ifdef DBG_LVL_3 printf("\n Updating global ptr\n"); #endif s = ptr; } } void sig_handler(int signo) { #ifdef DBG_LVL2 printf("\n Inside sig_handler\n"); #endif flag = 1; if (signo == SIGUSR1) printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else printf("ERR : received signal %d\n", signo); func(); #ifdef DBG_LVL2 printf("\n Done with sig_handler()\n"); #endif } int main(void) { #ifdef DBG_LVL1 printf("\n Inside main() \n"); #endif if (signal(SIGUSR1, sig_handler) == SIG_ERR) printf("\ncan't catch SIGUSR1\n"); if (signal(SIGUSR2, sig_handler) == SIG_ERR) printf("\ncan't catch SIGUSR2\n"); int i = 0; while(i<10) // Simulate a dummy wait { func(); i++; } free(s); #ifdef DBG_LVL1 printf("\n Exiting main() \n"); #endif return 0; } In the above code I have defined 3 Macros for 3 different levels of debugging statements(though they are commented, meaning that we do not want any debugging statement as of now). Now, for any type of debugging statements we just need to uncomment the corresponding macro and only those printfs will be activated. Macros can also be defined on basis of the environment our program will run. Like for example, we can have a piece if code under a macro which is defined only if the program is going to run in 64 bit environment. So like this there are various requirements where macros can easily save the day for us. Also, since macros are dealt with compile time only so there is no overhead of macros when the program is run. Macro with values Until now we discussed what are macros and how are they used. Here we will discuss concept of macros with values. Macros can be assigned values. Following is the example : Code: #define SIZE 10 The above line defines a macro SIZE with value 10. Here is a piece of code where we use the above macro : Code: #include<stdio.h> #include<stdlib.h> #define SIZE 10 int main(void) { char *ptr = (char*)malloc(SIZE); *ptr = 'a'; free(ptr); return 0; } Macros with values can be used for making the code better maintainable so that in future if we just want to change the value of number of bytes that are being passed in malloc() then only the value of macro SIZE is changed. This comes real handy in the cases where SIZE is being used at various places in the program So one needs to change the value of SIZE at one place and the change gets reflected at all the occurrences in the code. Defining a Macro from command line Until now we have seen how to define and enable Macro from within the code, now lets discuss how the same purpose can be achieved from command line. Lets go back to the very first program : Code: #include<stdio.h> int main(void) { #ifdef MYMACRO1 // test whether MYMACRO1 is defined? printf("\n MYMACRO1 Defined \n"); #endif #ifdef MYMACRO2 // test whether MYMACRO1 is defined? printf("\n MYMACRO2 Defined \n"); #endif return 0; } In this piece of code, I have just removed the definition of macros from within the code. Lets see how we achieve this from command line. I compile the code in the following way : Code: gcc -Wall -D MYMACRO1 -D MYMACRO2 macro.c -o macro And the output I get is : Code: $ ./macro MYMACRO1 Defined MYMACRO2 Defined You can verify this concept by compiling the code again without -D options and you will not get any output. Similarly, we can assign a value to a macro through command line and can access that value inside the code. Here is a piece of code explaining this : Code: #include<stdio.h> int main(void) { #ifdef MYMACRO1 // test whether MYMACRO1 is defined? printf("\n MYMACRO1 Defined with value[%d]\n",MYMACRO1); #endif #ifdef MYMACRO2 // test whether MYMACRO1 is defined? printf("\n MYMACRO2 Defined with value[%d]\n",MYMACRO2); #endif return 0; } I compile the code in the following way : Code: gcc -Wall -D MYMACRO1=2 -D MYMACRO2=4 macro.c -o macro And the output I get is : Code: $ ./macro MYMACRO1 Defined with value[2] MYMACRO2 Defined with value[4] Hence we see that we can send value based macros too. Conclusion To Conclude, this article presented a comprehensive explanation of macros, why are they used, where can they be helpful and different techniques to pass them.