社区讨论

关于未定义行为的一点疑问

学术版参与者 8已保存回复 17

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
17 条
当前快照
1 份
快照标识符
@lob69qfp
此快照首次捕获于
2023/10/29 15:51
2 年前
此快照最后确认于
2023/11/03 22:18
2 年前
查看原帖
群友提出的弔问题,原问题是这样的:
CPP
e[++tot]=(AC){1,a[i],i,0,tot}
这个写法是不是 UB,但是为了去掉一些不必要的因素,问题改为这个:
CPP
struct node{int x;}a[5];
int i=1;
a[++i]=(Node){i};
这个写法是不是 UB。
很显然,根据按顺序早于规则,C++ 11 起到 C++17 前的等于号左右两侧值计算和副作用的顺序没有规定,17 及以后才有先右后左的规定。所以结论是 17 及以后才不是 UB。

但是问题没有这么简单结束,我把这个代码放到 LuoguIDE 的 C++17 上跑,发现输出出现了问题:
CPP
#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 才对
然后我又测了下这个代码:
CPP
#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 扩展的复合字面量的问题,我测了下这个代码:
CPP
#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 的内容,所以有没有老哥能解释一下这是啥原因啊

回复

17 条回复,欢迎继续交流。

正在加载回复...