1

So I have the following program:

# define swap(a,b) temp=a; a=b; b=temp; 

int main() {
int i, j, temp;
i = 5;
j = 10;
temp = 0;
if (i > j)
    swap(i, j);
printf("%d %d %d", i, j, temp);
}

This results in:

10, 0, 0

What I don't understand is why the if (5 > 10) condition was executed as "true" even though 5 is not bigger than 10.

Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
Eric Bergman
  • 1,453
  • 11
  • 46
  • 84

2 Answers2

7

This should teach you to avoid macros if at all possible and always, always use braces in control flow statements.

After macro expansion, your code will read:

if (i > j)
    temp = i;
i = j;
j = temp;

See the problem?

Jon
  • 428,835
  • 81
  • 738
  • 806
  • I did not know how macros worked that's why it was confusing to me, I thought it was called like a function but instead it's being replaced at the time of compilation and since there are no braces only the first statement "temp = i" falls inside the if statement, makes sense, thank you ! – Eric Bergman Jan 26 '14 at 22:25
  • 2
    @EricBergman: This aspect of macros gives rise to a whole host of pitfalls. Classic examples: `#define add(x, y) x + y` (try `add(1, 2) * 3`) and multiple evaluation of arguments. This is why in production macros you see everything wrapped to death inside parens and braces. – Jon Jan 26 '14 at 22:32
  • In your experience, is there really a point to using macros? If you can make a normal function why ever use macros? I see you mentioned "production macros" so it sounds like it's something that is widely use for some specific purpose. – Eric Bergman Jan 26 '14 at 22:46
  • 1
    @EricBergman: There are cases where not using macros can be very tedious. One of the most notable is that macros are agnostic to the types of their arguments, while functions are not (and C has no overloading to help there). I don't feel comfortable making a case *for* macros because I 'm not battle-tested in C. OTOH it's true that the less you know, the more you abuse them. Just keep the option in your head but put it at the bottom of the list. – Jon Jan 26 '14 at 22:49
3

This is because at the time of compilation swap(i, j); is being replaced by temp=a; a=b; b=temp;. Now the expanded macro looks like

 if(i > j)
    temp = i;
    i = j;
    j = temp;  

At the time of execution only temp = i will not execute for i > j to be false.
If you wanna treat swap(i, j) like a function, then change your macro definition to

#define swap(a,b) do {temp=a; a=b; b=temp;} while (0) 
Brave Sir Robin
  • 1,046
  • 6
  • 9
haccks
  • 104,019
  • 25
  • 176
  • 264
  • Makes sense, this "trick" question was presented to me from a job interview but since I did not know how macros worked I got it wrong. I thought it was like a normal function call. Thank you. – Eric Bergman Jan 26 '14 at 22:27
  • 1
    @EricBergman; See the edit. Now your code will work as it should. – haccks Jan 26 '14 at 22:31