C 中增量运算符的工作原理
#include <stdio.h>
void main()
{
int x=5,y=6;
printf("%d%d%d",x++,(y=x++),(x=y++));
}
谁能解释一下为什么会返回 766?
#include <stdio.h>
void main()
{
int x=5,y=6;
printf("%d%d%d",x++,(y=x++),(x=y++));
}
Can anyone please explain why does this returns 766?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
首先,如果这个问题以这种格式出现在初级 C 编程课程中,那么课程/老师就很糟糕。
这里的主要问题是“x”和“y”在序列点之前被修改了几次,这是未定义的行为(C99/C11 6.5 §2)。这是一个严重的错误,因为任何事情都有可能发生。在清除 ++ 混乱之前,无法得知这段代码的作用。 阅读本文,然后再阅读。
此外,函数参数的求值顺序是未指定的行为。 (C99/C11 6.5.2.2 §10)。也就是说,编译器可能会从左到右或从右到左对它们进行计算,而我们无法知道适用哪种顺序。编译器不需要记录这一点!但如果你幸运的话,它可能会被记录下来。然后,在尝试回答问题之前,您必须阅读编译器文档以了解适用的评估顺序。否则你必须给出两个答案。
此外,如果这是托管系统(例如 Windows PC)的代码,则 main 只允许返回“int”,否则该代码将无法在 C 编译器上编译。
First, if this question, in this format, was given on a beginner C programming course, the course/teacher is a bad one.
The main problem here is that both 'x' and 'y' are modified several times before a sequence point, which is undefined behavior (C99/C11 6.5 §2). This is a severe bug, because anything can happen. Before the ++ mess is removed, there is no telling what this code does. Read this then read it again.
Further, the order of evaluation of function arguments is unspecified behavior. (C99/C11 6.5.2.2 §10). That is, the compiler may evaluate them left-to-right or right-to-left, and we cannot know which order that applies. The compiler does not need to document this! But if you are lucky, it could be documented. You must then read the compiler documentation to see which order of evaluation that applies, before attempting to answer the question. Otherwise you must give two answers.
Further, if this is code for a hosted system, such as a Windows PC, main is only allowed to return 'int' or this code won't compile on a C compiler.
您通过在序列点之间多次修改
x
来调用未定义的行为,所以您很幸运/不幸它根本打印了任何内容......You've invoked undefined behavior by modifying
x
more than once between sequence points, so you're lucky/unlucky it printed anything at all...是的,像这样的函数的参数解析顺序是未定义的。
处理像 printf 这样的可变参数函数的最简单方法是从末尾开始,因为您知道开始在哪里!
正如“R”指出的那样——评估不明确的语句是未定义的。
例如
x++ = x++
Yes, it's undefined what order the arguements to a function like this are parsed in.
The easiest way to handle a variable number of args function like printf is to start from the end, since you know where the beginning is!
As 'R' points out - it's undefined to have a statement where the evaluation is ambiguous.
eg
x++ = x++
这个工作堆栈概念作为提及操作 LIFO 第一个右操作数进入堆栈,即 x = y++ (这是后递增操作符,然后第一个 y 值在 y 将递增后分配给 x,即 x=6 ),然后是第二个(这里是 x = 6 且 y = 7 但 y 为 x 赋值为 6,则 x 将增加 1)和第三个(此处 x=7,在此语句之后 x 将增加 1 ) 值可能是 766。
This working stack concept as the mention operation LIFO firt right operand goes to the stack that is x = y++ (this is the post increament opratore then first y value assing to x after y will increament that is x=6 )then secound (here x = 6 and y = 7 but y is assign value of x that is 6 then x will increament by 1)and third (here x=7 and after this statement x will increament by 1 ) hance the values are 766.
它首先计算最后一个表达式
(x=y++)
。这将返回 6,因为 x 被分配了 y 的值,最初为 6,然后将 y 增加到 1。现在 y 为 7,x 为 6。此处打印 x。下一个要计算的表达式是
(y=x++)
。与上面相同,首先指定 y= x 并将 x 增加到 1。因此,值是 y 为 6,x 为 7。此处打印 y。现在是
x++
。它打印 7 并将 x 增加到 1。it first evaluates the last expression
(x=y++)
. This will return 6 because x is assigned with the value of y which is 6 initially and then it increments y to 1. Now y is 7 and x is 6. x is printed here.next expression to be evaluated is
(y=x++)
. Same as above first assign y= x and increment x to 1. So the values are y is 6 and x is 7. y is printed here.now
x++
. it prints 7 and increments x to 1.执行strts从右到左。所以,x=y++,x值变成6,之后y值变成7,然后y=x++,将y值恢复到6。之后在x++语句中x值是7,因为前面的陈述(y=x++)。答案也是如此 766
excecution strts frm right to left.So,x=y++,x value becomes 6 and after that y value become seven followed by y=x++,which restoe value of y to 6.After that in x++ statement x value is 7 due to the previous statement(y=x++).And so is the answer 766
想添加为什么它是从右端评估的,如前面的答案所提到的。 printf 的所有参数都被推入堆栈,然后开始计算。由于堆栈是后进先出的,因此计算从末尾开始。
Wanted to add why it's evaluated from the right end as previous answers mentioned. All the arguments of printf are pushed to a stack and then evaluation begins. As stack is LIFO, evaluation begins from the end.