群友提出的弔问题,原问题是这样的:
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 的内容,所以有没有老哥能解释一下这是啥原因啊