关于未定义行为的一点疑问
  • 板块学术版
  • 楼主MyukiyoMekyaZJunior
  • 当前回复17
  • 已保存回复17
  • 发布时间2021/12/13 10:43
  • 上次更新2023/11/3 22:18:29
查看原帖
关于未定义行为的一点疑问
51376
MyukiyoMekyaZJunior楼主2021/12/13 10:43

群友提出的弔问题,原问题是这样的:

e[++tot]=(AC){1,a[i],i,0,tot}

这个写法是不是 UB,但是为了去掉一些不必要的因素,问题改为这个:

struct node{int x;}a[5];
int i=1;
a[++i]=(Node){i};

这个写法是不是 UB。

很显然,根据按顺序早于规则,C++ 11 起到 C++17 前的等于号左右两侧值计算和副作用的顺序没有规定,17 及以后才有先右后左的规定。所以结论是 17 及以后才不是 UB。


但是问题没有这么简单结束,我把这个代码放到 LuoguIDE 的 C++17 上跑,发现输出出现了问题:

#include <cstdio> // LuoguIDE C++17
struct node{int 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 2 0 0 ,但是按照先右后左的顺序应该是输出 0 0 1 0 0 才对

然后我又测了下这个代码:

#include <cstdio> // LuoguIDE C++17
int a[5];
signed main(){
    int i=1;
    a[++i]=i;
    for(int i=0;i<5;++i)printf("%d ",a[i]);}

这下对了,输出是 0 0 1 0 0

然后我去 CF 上用 Clang++17 Diagnostics 测了下还是一样输出 0 0 1 0 0

问了下 @CE_WA_TLE ,他说可能是 GNU 扩展的复合字面量的问题,我测了下这个代码:

#include <cstdio> // CodeForces Clang++17 Diagnostics
struct node{int 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 文档并没有写这方面关于 UB 的内容,所以有没有老哥能解释一下这是啥原因啊

2021/12/13 10:43
加载中...