Wednesday 28 January 2015

Macros - Features of C Preprocessor

Welcome to Logically Proven Blog.
This post teaches you one of the important features of C preprocessor - Macro Expansion.

C preprocessor is a special program that processes source program before it is passed to the compiler. The preprocessor commands also known as directives. Each of these preprocessor directives begin with a # symbol. These directives can be placed anywhere in a source program but are most often placed at the beginning of a source program.

A million dollar question - Why Macro?
To made the program easier to read and understand.


Macro:

Have a look at the following program.
#include <stdio.h>
#define max 100
int main()
{
 printf("max is %d", max);
 return 0;
}
// Output: max is 100
// Note that the max inside "" is not replaced

In this program instead of writing 100 in the printf statement we are writing in the form of max, which has already defined before main() through the statement,
#define max 100
This statement is called macro. 

When we use define for a constant, the preprocessor produces a C program where the defined constant is searched and matching tokens are replaced with the given expression. In the above program max is defined as 100.


A #define directive could be used even to replace a condition as shown below -
#include <stdio.h>
#define AND &&
#define ARANGE ( a > 25 AND a < 50 )
int main()
{
 int a = 30;
 if (ARANGE)
  printf("within range");
 else
  printf("out of range");
 
 return 0;
}
// Output: within range
Note:
1. Macro template and macro expansion are separated by blanks or tabs.
2. A macro definition is never to be terminated by a semicolon.

Macro with Arguments:

The macros can take arguments like function, the arguments are not checked for data type, For example, the following macro INCREMENT(x) can be used for x of any data type.

#include <stdio.h>
#define INCREMENT(x) ++x
int main()
{
 char *ptr = "LogicallyProven";
 int x = 10;
 printf("%s  ", INCREMENT(ptr));
 printf("%d", INCREMENT(x));
 return 0;
}
// Output: ogicallyProven 11
An another example of macro with arguments which is checking for a condition -

#define ISDIGIT(x) ( x >= 48 && x <= 57 )

Note:

1. Do not leave a blank between the macro template and its argument while defining the macro.
    For example there is no blank between ISDIGIT and (x) in the definition above.

2. The entire macro expansion should be enclosed within parantheses.
     Consider a statement in a program: i= 64/SQUARE(4)

     Macro:    #define SQUARE(n) n*n        - Wrong  //output is 64 (64/4*4)
                      #define SQUARE(n) (n*n)      - Correct //output is 4 (64/(4*4))

     The macro arguments are not evaluated before macro expansion.


     This can be corrected using "inline functions".
   
   inline int square(int n) { return n*n; }
   int main()
   {
      int n = 64 / square(4);
      printf("%d", n);
      return 0;
   }
   // Output: 4

3. The macro can be written in multiple lines using '\'. The last line doesn't need to have '\'.

     Example:
                     #include <stdio.h>
            #define PRINT(i, limit) while (i < limit) \
                      { \
                             printf("GeeksQuiz "); \
                             i++; \
                      }
Token-Pasting operator:

The tokens passed to macros can be concatenated using operator ## called token-pasting operator.

#include <stdio.h>
#define merge(a, b) a##b
int main()
{
 printf("%d ", merge(12, 34));
}
// Output: 1234
String converter:

A token passed to macro can be converted to a string by appending # before it.
#include <stdio.h>
#define get(a) #a
int main()
{
 // LogicallyProven is changed to "LogicallyProven"
 printf("%s", get(LogicallyProven));
}
// Output: LogicallyProven
Standard macros:

There are some standard macros which can be used to print the program file, date of compilation, time of compilation and line number in C code.

#include <stdio.h>
int main()
{
 printf("Current File :%s\n", __FILE__);
 printf("Current Date :%s\n", __DATE__);
 printf("Current Time :%s\n", __TIME__);
 printf("Line Number :%d\n", __LINE__);
 return 0;
}
 
/* Output:
Current File :D:\myCB\ifcondition\LogicallyProven\main.c
Current Date :Jan 28 2015
Current Time :17:45:45
Line Number :7 */

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Logically Proven
learn, teach, share

Karthik Byggari

Author & Editor

Computer Science graduate, Techie, Founder of logicallyproven, Love to Share and Read About pprogramming related things.

0 comments:

Post a Comment

 
biz.