我正在使用新的_Generic
关键字进行一些实验,并偶然发现了一个有关多个评估的特殊情况。请参阅以下内容:
#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');
}
编译好并使用GCC产生预期结果:
$ gcc -std=c11 -Wall plusplus.c -o plusplus
$ ./plusplus
foo
另一方面,Clang输出了一个很大的鸣喇叭警告:
$ 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)
...
然而结果如预期:
$ ./plusplus
foo
我查了the draft of the standard,其中说(在PDF的第97页):
不评估通用选择的控制表达式。
这似乎可以准确地解决宏中的副作用问题(例如MIN
和MAX
)。
现在,我可以放心地忽略Clang的警告,还是我错了?
答案 0 :(得分:3)
正如我在评论中提到的那样,你在Clangs主干中修复了错误两周后发布了这个问题。见修订版rL223266(2014年12月3日)。修正案包含在Clang 3.6中。
现在,我可以放心地忽略Clang的警告,还是我错了?
我们已经知道你是对的,所以这里有一种方法可以忽略Clang中的pragma 未来:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsequenced"
write_char(*s++);
#pragma clang diagnostic pop
要在每次使用宏时不重复,可以将_Pragma放在其正文中:
#define write_char(c) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wunsequenced\"") \
_Generic(c, char: putchar, const char: putchar)(c) \
_Pragma("clang diagnostic pop")
答案 1 :(得分:0)
这似乎是一个错误。从clang
3.6开始,它已经解决,如here所示。