There are macros where you're concatenating elements to make a string (perhaps using the #
operator), or building identifiers out of macro arguments using the ##
operator. In such cases, you don't parenthesize the arguments.
Also, I think that when the macro arguments are themselves passed as function arguments, then you don't absolutely have to parenthesize them:
#define CALLOC(s, n) calloc(s, n)
You can play fiendish games calling such a macro (CALLOC({3, 4})
), but you get what you deserve (a compilation error) — I'm not aware of a way of calling that macro that would work if instead of the macro you wrote the same arguments as a direct call to calloc()
.
However, if you are using the arguments in most arithmetic expressions, then you do need to wrap them in parentheses:
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
Obviously, if you invoke it with arguments with side effects, then you get what you get. But the arguments won't be misinterpreted as they could be if you wrote:
#define MIN(x, y) x < y ? x : y
and then invoked it as:
MIN(x = 3 * y + 1, y = 2 * x - 2);
The comment by Moon suggests a SWAP_INT
macro.
The following code using that macro compiles cleanly when compiled using default options, but fails to compile with -DWITH_PARENTHESES
set.
#include <stdio.h>
#ifdef WITH_PARENTHESES
#define SWAP_INT(a, b) do { int temp = (a); (a) = (b); (b) = temp; } while (0)
#else
#define SWAP_INT(a, b) do { int temp = a; a = b; b = temp; } while (0)
#endif
int main(void)
{
int p = 319;
int q = 9923;
int x = 23;
int y = 300;
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(p, q); // OK both ways
SWAP_INT(x, y); // OK both ways
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(x /= y, p *= q); // Compiles without parentheses; fails with them
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
return 0;
}
The output:
p = 319, q = 9923, x = 23, y = 300
p = 9923, q = 319, x = 300, y = 23
p = 41150681, q = 13, x = 0, y = 3165437
That isn't a safe or effective way of swapping integers — the macro without the parentheses is not a good idea.
JFTR: when compiled without -DWITH_PARENTHESES
, the line for the macro with the expressions is inscrutable:
do { int temp = x /= y; x /= y = p *= q; p *= q = temp; } while (0);
Normally, a swap macro expects two variable names — or array elements, or structure or union members, or any mix of these. It does not expect to be given arbitrary expressions. The parentheses ensure that the assignment to x /= y
(which is not an lvalue) fails; without the parentheses, the expression is interpreted, but it isn't anything like what was intended (if, indeed, anything could be intended when 'swapping' two expressions like that).