Thursday 27 June 2013

[C: Facts#1] Test our C skills

I will share some facts about C language those I encountered when I used macros in my assignments and today also I found one interesting thing about macros definition.
If we are not define macro in proper way then our program will end up with unexpected results.
A Simple macro definition is

#define square(x) (x * x)
This macro replaces the square(x) with (x * x) in the program.
Example:


  1. #include<stdio.h>
  2. #define square(x) (x * x)

  3. void main()
  4. {
  5.    int val = 5;

  6.     printf("Before square: val = %d\n", val);
  7.  printf("Square of val++ is: %d \n", square(val++));
  8.  printf("After square: val = %d\n", val);
  9. }

Output:
Before square: val = 5
Square of val++ is: 25
After square: val = 7

Explanation: 
The intention our programmer would be square of 6 (if val = 5, val++ is 6). But, square(val++) at line no 9 will be replaced by (val++ * val++) after compilation. Now, the val is replaced in the expression (val++ * val++) and it looks like (5 * 5) and finally, the ans will be 25.
When the expression (val++ * val++) is evaluated, the val value is 5 and the increment type is post increment, so, this increment is not reflected on val at this moment. So, 5 is assigned at val++ positions, and leads to (5 * 5).
And, after this expression the val value becomes 7, as val is incremented twice.

Experiment_2:
Even if we replace square(i++) by square(i+1), then also we see problem.
Since, square(i+1) will be replaced by (i+1 * i+1), and in turn it leads to (i + (1 * i) + 1) since multiplication has more priority over addition.
So, that output is 5 + (1 * 5) + 1 = 11.
Solution: Use pair of brackets for each macro parameter.
i.e. ((i + 1), (i + 1)) ==> ((5 + 1), (5 + 1)) = ((5 + 1) * (5 + 1)) = (6 * 6) = 36

Experiment_3:
If we declare multiple statements for a macro then it is advised to use/call the macro within braces.
For example, if code snippet looks like below
#define macro_1(value) printf("value: %x\n", value); printf("blah blah\n");

if (value < 1)
     macro_1(value);

After compilation, the code will look like below
if(value < 1)
     printf("value: %x\n", value);
printf("blah blah\n");
So, the 2nd printf will be executed for all cases.
Solution: To avoid this type of behavior, please use braces around macros.
if (value < 1) {
     macro_1(value);
}
or use braces in the macro definition.
macro_1(value) { printf("value: %x\n", value); printf("blah blah\n"); }

This will helpful even in case of the macros which having if else conditional statements. Example,
macro_2(value) if (value != 0) printf("value: %x\n", value); else printf("blah blah\n");

I hope this post will make us to think twice before we use macros in our code.
Please post your suggestions on any useful info regarding macro use.
If you find anything is wrong here then please add your comments.
Thank you.

No comments:

Post a Comment

You might also like

Related Posts Plugin for WordPress, Blogger...