对吧,未定义就是 UB,参加 SF 的一篇博文
by zhy137036 @ 2020-03-14 18:06:08
https://studyingfather.blog.luogu.org/undefined-behavior
by zhy137036 @ 2020-03-14 18:07:21
最好不要把++n写到中括号里面。
写到外面程序稳定些,不易出错,同时代码可读性很高
by PersistentLife @ 2020-03-14 18:10:18
我本地亲测效果如下:
DEVC++应该是你要的效果,即n++后-1
VS是前面调用n+1,后面调用n-1?
不过考虑到我这边的两个IDE使用的Mingw版本不同,有如下结论:
**全看编译器怎么看**
更重要的是,这个问题普通-o编译无法显示,**-Wall 大法好!**
~~(顺便说一句:Warning != Error,大部分情况下不用管)~~
by 水無月嘉祥 @ 2020-03-14 18:11:20
@[水無月嘉祥](/user/215954) 你那句话太误导人了吧
by jyttoby @ 2020-03-14 18:17:43
@[水無月嘉祥](/user/215954) Warning 不能不管吧,像 `if(a=1)` 这种都能查出来
by zhy137036 @ 2020-03-14 18:29:37
显然是先算右边的等式再赋值(copy)到左边去
by RedreamMer @ 2020-03-14 18:30:29
@[ラブアロ](/user/224236) 这不是++的问题,这是**赋值运算符结合律与求值顺序**的问题。
C++规定:赋值运算符满足**右结合律**。意思是说,如果有多个赋值运算符连写:
```cpp
i = j = k = 1;
```
那么“右结合律”将发挥作用,它跟下面的写法等价:
```cpp
i = (j = (k = 1));
```
也就是说,先执行```k=1```,再把它的值赋给`j`,再赋给`i`。这是所谓的“右结合律”
但是C++只规定了运算符的结合律和优先级,**没有规定运算对象的求值顺序**。也就是说:
```cpp
a[f()] = a[g()] = a[h()];
```
这样的语句,你无法知道f,g,h这三个函数究竟谁先调用、谁后调用。你只能知道:编译器会先将`a[h()]`的结果赋值给`a[g()]`,再将它赋值给`a[f()]`。
看到了,这是结合律和优先级的局限性,哪怕规定了结合律和优先级,这些运算对象的求值顺序依然是不确定的。
这时候就能解释了:
```cpp
a[++n] = a[n - 1] ^ x;
```
这样的代码,究竟++n先运算还是n-1先运算是**未定义的**。
by GKxx @ 2020-03-14 18:50:45
@[qiliangzhe](/user/300025) 你这个说法是不对的,结合律并不能规定运算对象的求值顺序
by GKxx @ 2020-03-14 18:52:27
@[ラブアロ](/user/224236) 我以前还犯过一个典型错误:
```cpp
inline int read() {
// 读入优化
}
inline void addedge(int x, int y, int w) {
// 添加一条从x到y的有向边,边权是w
}
int main() {
n = read(); m = read();
for (int i = 1; i <= m; ++i)
addedge(read(), read(), read());
}
```
这里的`addedge(read(), read(), read());`出了问题,这三个read函数不知道哪个会先被调用。
by GKxx @ 2020-03-14 19:00:47