我正在用新的 _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 页):
The controlling expression of a generic selection is not evaluated.
这似乎准确地解决了宏中的副作用问题(例如,MIN
和 MAX
)。
现在,我可以安全地忽略 Clang 的警告吗?还是我错了?
最佳答案
正如我在评论中提到的,您在 Clangs 主干中修复错误大约两周后发布了问题。请参阅修订 rL223266 (2014 年 12 月 3 日)。该修复包含在 Clang 3.6 中。
Now, can I safely ignore Clang's warning, or am I wrong?
我们已经知道你是对的,所以这里有一种方法可以忽略 Clang 中的编译指示 future :
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsequenced"
write_char(*s++);
#pragma clang diagnostic pop
为了不在每次使用宏时都重复它,您可以输入 _Pragma在它的 body 里:
#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")
关于c - 泛型表达式的副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27584048/