有人能告诉我幕后发生了什么吗?
main()
{
int z, x=5, y=-10, a=4, b=2;
z = ++x - --y*b/a;
printf("%d", z);
}
答案 0 :(得分:3)
编写代码的奇怪方式...无论如何......我试试......
++x
和--y
因此...
z= 6 - (-11) * 2 /4
z= 6 - (-22) / 4
z= 6 - (-5)
(由于(-22) / 4
是整数除法,结果被截断)我得到z= 11
。
变量z
被声明为int,因此变为11
。
我建议以更简单的方式写这行!哦......对不起我的英文......
答案 1 :(得分:2)
此表达式
z=++x - --y*b/a;
在抽象机器中按以下顺序进行评估
变量x
递增并等于6。
变量y
递减并变为等于-11。
变量y乘以变量b
,结果等于-22。
前面操作的结果除以变量a
,因为使用整数运算,结果等于-5。
最后从变量x中减去结果,结果等于11。
运行程序并确定我是否正确。
考虑到特定实现可以以不同的顺序评估操作数,前提是结果与我为抽象机器描述的结果相同。
根据C标准(5.1.2.3程序执行)
4在抽象机器中,所有表达式都按指定的方式进行计算 通过语义。实际的实现不需要评估部分内容 表达式,如果它可以推断出它的值没有被使用而且没有 产生所需的副作用(包括通过调用a引起的任何副作用) 功能或访问易失性对象。)
答案 2 :(得分:1)
首先,请注意 运算符优先级 与 子表达式评估顺序 之间的区别。
运算符优先级指示在将这些操作的结果与表达式的其余部分一起使用之前必须执行和评估的操作。这类似于数学优先级:1 + 1 * 2
保证给出结果3,而不是4.因为*
的优先级高于+
。
评估顺序等于实际的执行顺序,并且是未指定的行为,这意味着编译器可以按照自己喜欢的任何顺序自由执行各种子表达式,为了生成最快的代码。我们无法了解订单。 C中的大多数运算符涉及未指定的评估顺序(除&& || ?: ,
之类的特殊情况外)。
例如,在x = y() + z()
的情况下,我们可以知道+
操作将在=
之前执行,但我们无法分辨哪些函数{{将首先执行的1}}和y
。取决于函数的作用,结果可能或可能无关紧要。
然后到问题中的表达式:
z
和++x
,因为前缀一元运算符的优先级高于表达式中存在的那些。--y
和++x
的子表达式。我们无法告诉执行的顺序(而--y*b/a
反过来又包含几个子表达式)。无论如何,评估的顺序在这里并不重要,它不会影响结果。--y*b/a
和++x
将在这些操作的结果与表达式的其余部分一起使用之前发生。--y
和*
的操作。这些运算符具有相同的优先级,但它们属于乘法运算符组,具有从左到右的关联性,这意味着/
可以保证首先评估--y*b/a
。之后,结果将除以--y*b
。 a
。( (--y) * b ) / a
的优先级高于-
。因此,子表达式=
的结果将被子表达式++x
的结果减去。--y*b/a
,因为z
的优先级最低。修改强>
顺便说一下,编写相同内容并获得相同机器代码的正确方法是:
=
除了降低可读性之外,++和 - 运算符与其他运算符混合是危险的,因为它们包含副作用。每个表达式有多个副作用很容易导致各种形式的无序处理,这总是一个错误,可能很严重。 See this例如。
答案 3 :(得分:0)
"运营商优先级"表示用于确定每个运算符的操作数的规则。在您的情况下,使用括号表示:
z=++x - --y*b/a;
相当于:
z = ((++x) - (((--y) * b) / a));
现在,这行代码和以下printf
语句具有与代码相同的可观察行为:
z = (x + 1) - ((y - 1) * b / a);
printf("%d\n", z);
x = x + 1;
y = y - 1;
C是根据可观察行为定义的(大约是指程序生成的输出;您可以通过阅读C标准看到技术定义)。根据标准产生相同可观察行为的任何两个程序被认为是完全等效的。
这有时被称为" as-if规则"正是这条规则允许优化发生。
解决其他一些答案提出的问题:
确切地说明了++
和--
的作用的规则。具体而言,定义递增x
和递减y
的效果,以便在执行z=++x - --y*b/a;
期间的任何时间发生递增和递减的回写。它们可以是任何顺序,也可以是同时的;减量的写入可以在计算(y-1) * b
之前或之后,等等。
在一些不同的代码示例中,我们将使用这些规则来计算程序的可观察行为,并且它不会像这个特定程序那么灵活。
但是在这个代码示例中,因为没有别的东西取决于那些增量和减量的时间,所以我们甚至可以将它们提升到printf
之后,根据" as-if规则& #34;