使用 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?)初始化结构的奇怪现象的主要内容,如果未能解决你的问题,请参考以下文章

Qt 2D绘图之三:绘制文字路径图像复合模式

C++ - 使用 const 引用来延长一个临时的、好的或 UB 的成员?

c ++改变cin也许是skipline?

如何在 C++ 中获得没有 UB 的浮点位表示?

C++ 严格别名:这不是 MSFT 示例 UB 吗? [复制]

使用valgrind时出现奇怪的错误?也许是一个错误?