3
#define swap(a,b) a = a ^ b; b = a ^ b; a = a ^ b;
int main()
{
    swap(a,b)
}

Gives correct answer.

#define swap(a,b) (a = a ^ b; b = a ^ b; a = a ^ b;)
int main()
{
    swap(a,b)
}

Gives a compilation error : "expected ')' before ';' token"

#define swap(a,b) ({a = a ^ b; b = a ^ b; a = a ^ b;})
int main()
{
    swap(a,b); //note the semicolon at the end, without that the compiler gives an error
}

works fine.

Now my confusion is why the second doesn't work? I think it should work perfectly. And secondly why should I need to put a semicolon at the end of the macro call in the third?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Those are usually to avoid unwanted stuff to happen when the macro is used in an expression where operator precedence could otherwise change the meaning. But in this example that's not an issue. – Blaze Apr 26 '19 at 13:56
  • 3
    As a rule of thumb: if you find yourself writing semi-colons in a macro, it should very likely have been written as a function instead. – Lundin Apr 26 '19 at 13:59
  • 3
    This `AREA(r) (PI * r * r)` should have looked like this `AREA(r) (PI * (r) * (r))` – alk Apr 26 '19 at 14:00
  • @alk that's a good tip. For instance, `AREA(2.0 - 1.0)` would incorrectly result in `3.283185` instead of `3.141593` without these extra parentheses. – Blaze Apr 26 '19 at 14:10

2 Answers2

6

If you expand the macro out, the three of them look like this:

a = a ^ b; b = a ^ b; a = a ^ b;
(a = a ^ b; b = a ^ b; a = a ^ b;)
({a = a ^ b; b = a ^ b; a = a ^ b;});

The first is fine. The second is a syntax error: you can't surround multiple statements with parentheses. It's not a thing. The third uses a GCC extension called statement expressions. You can surround a set of statements with ({ ... }) to treat it like an expression.

Note that the standard idiom for having multiple statements in a macro is a do { ... } while (0) loop with no trailing semi-colon.

#define swap(a,b) do { a = a ^ b; b = a ^ b; a = a ^ b; } while (0)
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 2
    @Sami As an aside, most expect a `swap()` function or macro to be able to handle both arguments being the same. This trickery will zero it instead. – Deduplicator Apr 26 '19 at 14:12
2

The preprocessor substitutes macro definitions with a string, and the resulting source code gets then compiled. For Example 2 your resulting source code would be:

int main()
{
    (a = a ^ b; b = a ^ b; a = a ^ b;)
}

and that is not valid C code; that's why your compiler is complaining. This should also answer your second question.

Try it out with gcc -E mycode.c. -E tells gcc to stop the compilation process after the preprocessor has run.

user3469811
  • 676
  • 1
  • 5
  • 17