Sunday, November 10, 2013

One tip on C macros

I am not a computer science graduate so when I started my career I knew only two languages Hindi and English. I later moved into IT industry as almost every other guy was doing. I went through a crash course on 'C' and before I could learn any other language, my company decided to move me into a client's project. I usually joke when I say I now know three language Hindi, English and 'C' but that is a fact. Since then I have worked on some more computer languages like C++, Perl and Python but I have always felt more comfortable with 'C'.

As I mentioned I learned the basic of 'C' in a 5 days crash course and most of what I now know, I learned from my peers of my various projects. During this time, I first learned what is the right way of writing 'C' macros and later found the explanation of why that is the right way. I decided to share some of those with you in multiple post. So here is the first one.

Let us assume you created a macro as follows:

#define  MULTIPLY_BY_TEN( x, y )                x = y * 10

Let us assume the usage of this macro is as mentioned below.

multiply_by_ten_function( one_time )
{
     unsigned long      ten_times;

     MULTIPLY_BY_TEN( ten_times, one_time );

     return ten_times;
}

Do you see anything wrong in this? No. I also don't see anything wrong. Actually in this usage, there is nothing wrong. But what do you think about the below usage?

multiply_by_ten_function( one_time, two_time )
{
     unsigned long      ten_times;

     MULTIPLY_BY_TEN( ten_times, one_time + two_time );

     return ten_times;
}

Yes. This will have a problem. Why? Because when the macro is expanded it will be :

multiply_by_ten_function( one_time, two_time )
{
     unsigned long      ten_times;

     ten_times = one_time + two_time * 10;

     return ten_times;
}

Instead of the addition of 'one_time' and 'two_time' first, it will multiply two_time with 10 and then add one_time to the result. So how do we fix such a thing? Very simple. We always wrap the arguments of a macro with '()'. Now let us look at the macro again:

#define  MULTIPLY_BY_TEN( x, y )                (x) = (y) * 10

Now this is how it will look after expanding:

multiply_by_ten_function( one_time, two_time )
{
     unsigned long      ten_times;

     (ten_times) = (one_time + two_time) * 10;

     return ten_times;
}

And you will get exactly what you expected. So I hope you will change your habit of not wrapping the arguments of macro with '()'. Please don't believe me and do try this out by writing a small 'C' code to validate the above.

I will put up more such tips in future post. If you want me to write about anything in particular, please leave me a comment.