I'm doing some experiments with the new _Generic
keyword and stumbled upon a special case regarding multiple evaluations. See the following:
#include <stdio.h>
#define write_char(c) _Generic(c, char: putchar, const char: putchar)(c)
int main(void)
{
const char *s = "foo";
write_char(*s++);
write_char(*s++);
write_char(*s++);
putchar('\n');
}
This compiles fine and produces the expected result with GCC:
$ gcc -std=c11 -Wall plusplus.c -o plusplus
$ ./plusplus
foo
On the other hand, Clang outputs a big honking warning:
$ clang -std=c11 plusplus.c -o plusplus
plusplus.c:9:18: warning: multiple unsequenced modifications to 's'
[-Wunsequenced]
write_char(*s++);
^~
plusplus.c:3:32: note: expanded from macro 'write_char'
#define write_char(c) _Generic(c, char: putchar, const char: putchar)(c)
...
Yet the result is as expected:
$ ./plusplus
foo
I checked the draft of the standard, which says (at p. 97 of the PDF):
The controlling expression of a generic selection is not evaluated.
This seems to precisely address the problem of side-effects in macros (e.g., MIN
and MAX
).
Now, can I safely ignore Clang's warning, or am I wrong?