C +;=操作员链接(带有UB的破折号)

C +;=操作员链接(带有UB的破折号),c,pointers,chaining,undefined-behavior,C,Pointers,Chaining,Undefined Behavior,我知道分号之前没有序列点,但是对于解引用指针在表达式中使用旧值2,是否有合理的解释 或者可以简单地说是未定义的行为 int i=2; int *x=&i; *x+=*x+=i+=7; 结果: i= 13 这是“简单的”未定义的行为 也就是说,编译器可能会发出代码,读取i的值一次,然后执行所有算术运算,然后存储i的新值 找到真正解释的明显方法是查看编译器生成的程序集。这是“简单”的未定义行为 也就是说,编译器可能会发出代码,读取i的值一次,然后执行所有算术运算,然后存储i的新值 找出真

我知道分号之前没有序列点,但是对于解引用指针在表达式中使用旧值2,是否有合理的解释

或者可以简单地说是未定义的行为

int i=2;
int *x=&i;
*x+=*x+=i+=7;
结果:

i= 13
这是“简单的”未定义的行为

也就是说,编译器可能会发出代码,读取
i
的值一次,然后执行所有算术运算,然后存储
i
的新值

找到真正解释的明显方法是查看编译器生成的程序集。

这是“简单”的未定义行为

也就是说,编译器可能会发出代码,读取
i
的值一次,然后执行所有算术运算,然后存储
i
的新值


找出真正解释的明显方法是查看编译器生成的程序集。

行为不是未定义的,而是编译器分解表达式并将中间结果推送到堆栈上的方式。首先计算两个
*x
s(两者均等于2),并将其推送到堆栈上。然后
i
加上7等于9。然后,第二个仍然等于2的
*x
,从堆栈中拉出,并添加到11中。然后将第一个
*x
从堆栈中拉出并添加到11中,形成13


查找反向波兰语表示法以了解此处发生的情况。

行为并不是未定义的,它取决于编译器分解表达式并将中间结果推送到堆栈上的方式。首先计算两个
*x
s(两者均等于2),并将其推送到堆栈上。然后
i
加上7等于9。然后,第二个仍然等于2的
*x
,从堆栈中拉出,并添加到11中。然后将第一个
*x
从堆栈中拉出并添加到11中,形成13


查看反向波兰语符号以了解此处发生的情况。

这绝对是未定义的行为,与stacks无关。好吧,如果某个表达式多次更改某个变量,则为UB。如果x没有指向我,那将是一个不同的故事。也许。@eq,@Sergey,我想你可能误解了编译器是如何分解这一行的。它不会从左到右对其求值,而是根据优先级规则将其分解,并存储中间结果。我对正在发生的事情的描述是正确的。一个表达式可以多次更改变量,但如果您理解并遵循优先级规则,并且知道编译器如何工作,那么表达式的结果就不是未定义的行为。@Kernow:不,您似乎误解了编程语言“C”,它是根据C标准定义的(最新版本“ISO/IEC 9899:1999”)。在这种情况下,“未定义的行为”是标准未明确定义的操作的结果。其中一个例子是多次修改变量,其间没有序列点。一个合格的C编译器可能会产生一个完全没有价值的程序——或者干脆崩溃;编程语言“C”不会让您对此有更多的了解。在这种情况下,优先级规则不会定义实际的操作顺序。这绝对是未定义的行为,与堆栈无关。AFAIK,如果某个表达式多次更改某个变量,则为UB。如果x没有指向我,那将是一个不同的故事。也许。@eq,@Sergey,我想你可能误解了编译器是如何分解这一行的。它不会从左到右对其求值,而是根据优先级规则将其分解,并存储中间结果。我对正在发生的事情的描述是正确的。一个表达式可以多次更改变量,但如果您理解并遵循优先级规则,并且知道编译器如何工作,那么表达式的结果就不是未定义的行为。@Kernow:不,您似乎误解了编程语言“C”,它是根据C标准定义的(最新版本“ISO/IEC 9899:1999”)。在这种情况下,“未定义的行为”是标准未明确定义的操作的结果。其中一个例子是多次修改变量,其间没有序列点。一个合格的C编译器可能会产生一个完全没有价值的程序——或者干脆崩溃;编程语言“C”不会让您对这一点有更多的了解。在这种情况下,优先级规则不会定义实际的操作顺序。