【发布时间】:2014-12-20 20:29:03
【问题描述】:
我正在用新的 _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 的警告,还是我错了?
【问题讨论】:
-
听起来您应该向 Clang 开发团队报告问题,而不是忽略它。您可能是第一个遇到该问题的人。当你写
putchar(*s++)时会发生什么?这也会产生警告吗?大概不会。 -
我认为你在 clang 中发现了一个错误!
-
@PascalCuoq,不,它不相关。那里观察到的警告是有道理的。这不是,在给定的代码中没有对
++的未排序评估。 -
@doukremt,我不知道您是否已经提交了错误(在错误跟踪器中看不到它),但是在尝试了您的示例并且没有看到任何错误之后,我查看了 Clang 中的提交历史记录并从 2014 年 12 月 3 日找到this commit。所以它实际上是一个错误,并且已经修复。
-
@xaizek 供未来读者参考,您可以将其发布为问题的正确答案。