使用 GNU C++ 的复合文字(也许是 UB?)初始化结构的奇怪现象
Posted
技术标签:
【中文标题】使用 GNU C++ 的复合文字(也许是 UB?)初始化结构的奇怪现象【英文标题】:A strange phenomenon to initialize struct with GNU C++'s Compound Literals (maybe UB?) 【发布时间】:2022-01-16 15:12:24 【问题描述】:#include <cstdio> // GCC C++17
struct nodeint x;a[5];
signed main()
int i=1;
a[++i]=(node)i;
for(int i=0;i<5;++i)printf("%d ",a[i].x);
从 C++17 开始,a[++i]=i
不是 UB。
根据Sequenced-before规则,
a[++i]=i
等价于a[i+1]=i , i+=1
。 (在 C++17 中)
但是为什么上面的代码运行输出0 0 2 0 0
而不是0 0 1 0 0
?
当我尝试时:
#include <cstdio> // GCC C++17
struct nodeint x;node()x=0;node(int _x)x=_x;a[5];
signed main()
int i=1;
a[++i]=node(i);
for(int i=0;i<5;++i)printf("%d ",a[i].x);
没有这个问题,输出0 0 1 0 0
。
我阅读了 GNU 文档,但找不到有效信息。
那到底是怎么回事?
【问题讨论】:
复合文字不是 C++17 的一部分,因此您可以将第一个示例转为聚合初始化(这对于 gcc Demo 仍然存在问题) 对于固定版本,gcc 会错误警告序列点Demo @Jarod42 谢谢,但我发现了另一个问题:Demo它还报告了g++17下的[-Werror=sequence-point]。为什么? 我会说 gcc 错误。 【参考方案1】:我不认为这是一个错误。当写A = B
,其中A
是一个对象时,你调用的是编译器生成的函数operator=()
,这个函数的第一个参数是this
。所以你应该寻找函数参数的评估顺序(未定义)。
【讨论】:
【参考方案2】:我会说这是一个编译器错误。我用 clang 13.0.0 尝试了你的代码,它产生了你想要的输出。与 icx 3.0 相同。
但正如在 cmets 中指出的那样,复合文字不是 C++17 标准的一部分,因此您不能仅仅通过查看标准就完全期望它会起作用。
【讨论】:
以上是关于使用 GNU C++ 的复合文字(也许是 UB?)初始化结构的奇怪现象的主要内容,如果未能解决你的问题,请参考以下文章
C++ - 使用 const 引用来延长一个临时的、好的或 UB 的成员?