简体   繁体   English

C 中的 while 循环条件中的组合赋值运算符

[英]Combined assignment operator in a while loop condition in C

I really have a hard time understanding how the following piece of code works:我真的很难理解以下代码是如何工作的:

int x = -2;

while ( --x > -10 && (x -= 2)) {
    printf ( " %d," , x ) ;
}
printf ( " %d" , x ) ;

output:   -5, -8, -11, -12

I mean I get what我的意思是我得到了什么

while ( --x > -10)

output:  -3, -4, -5, -6, -7, -8, -9, -10

and

while (x -= 2)

output: -> infinte loop

alone would do, but how do they work with the and operator?单独就可以,但是它们如何与 and 运算符一起工作? I mean for "while (x -= 2)" the condition is only met when x = 2, so how can the while loop even end and not go infinite like it does when only "while (x -= 2)" is used?我的意思是“while (x -= 2)”的条件只有在 x = 2 时才会满足,所以 while 循环如何才能结束而不是 go 无限,就像只使用“while (x -= 2)”时那样?

The fact that you start with -5 is quite obvious:以 -5 开头的事实非常明显:

int x = -2;
while ( --x > -10 && (x -= 2)) {

--x turns x from -2 into -3. --xx从 -2 变为 -3。
x -= 2 turns x from -3 into -5. x -= 2x从 -3 变为 -5。

... and so it goes further: using --x and x -= 2 you decrement again by 3, so you get values like -8 and -11. ...所以它更进一步:使用--xx -= 2你再次减 3,所以你得到像 -8 和 -11 这样的值。 (When you reach -11, you already checked for "> -10", which was -9 at that moment) (当您达到 -11 时,您已经检查了“> -10”,当时是 -9)

Then, again you do --x , turning -11 into -12, but you jump out of the while loop and you print that new value again.然后,您再次执行--x ,将 -11 变为 -12,但您跳出 while 循环并再次打印该新值。

Edit, more clarification:编辑,更多说明:

x -= 2 means x=x - 2 , it's not some kind of a check. x -= 2表示x=x - 2 ,这不是某种检查。

Value of x                 Output

In the first loop:
   x = -3, x = -5                 -5
In the sec loop:
   x = -6, x = -8                 -8
In the third loop:
   x = -9, x = -11                -11
In the fourth loop -> exits the while loop since x > -10:
   x = -12, x = -14              -12

The test is purposely obfuscated.测试是故意混淆的。 Here are the steps:以下是步骤:

  • --x > -10 always decrements x and compares the resulting value to -10 , breaking from the loop if x reaches -10 or below. --x > -10总是递减x并将结果值与-10进行比较,如果x达到 -10 或更低,则退出循环。
  • if x >= -10 from the previous test, (x -= 2) further decreases the value of x by 2 and tests whether the resulting value is non zero.如果前一个测试中的x >= -10 ,则(x -= 2)进一步将x的值减少 2 并测试结果值是否非零。 The only value of x for which (x -= 2) is zero is x = 2 . (x -= 2)为零的x的唯一值是x = 2 In the present case, x is always negative so this test is always true.在本例中, x始终为负,因此该测试始终为真。

starting from x = -2 , the iterations are:x = -2开始,迭代是:

  • --x -> x = -3 , the comparison is true --x -> x = -3 ,比较为真
    (x -= 2) -> x = -5 , printf outputs -5 (x -= 2) -> x = -5 , printf输出-5

  • --x -> x = -6 , the comparison is true --x -> x = -6 ,比较为真
    (x -= 2) -> x = -8 , printf outputs -8 (x -= 2) -> x = -8printf输出-8

  • --x -> x = -9 , the comparison is true --x -> x = -9 ,比较为真
    (x -= 2) -> x = -11 , printf outputs -11 (x -= 2) -> x = -11printf输出-11

  • --x -> x = -12 , the comparison is false, the loop is exited --x -> x = -12 ,比较为假,退出循环

  • the final printf outputs -12最后的printf输出-12

The code is unnecessarily obfuscated...代码被不必要地混淆了......

You are right that while ( x -= 2 ) would result in an infinite loop.没错, while ( x -= 2 )会导致无限循环。

However, C has (what are known as) short circuit operators .然而,C 有(所谓的)短路算子

Thus in the expression while ( --x > -10 && (x -= 2) ) the second term is only evaluated when the first term is true.因此,在表达式while ( --x > -10 && (x -= 2) )中,仅当第一项为真时才计算第二项。

Therefore, while the first term --x > -10 holds true, the second term (x -= 2) is also evaluated... once the first term becomes false, the second term is not evaluated, and the loop exits with just the single pre-decrement... resulting in the output you observe.因此,虽然第一项--x > -10成立,但第二项(x -= 2)也被计算...一旦第一项变为假,第二项就不会被计算,并且循环仅退出单个预减量...导致您观察到的 output 。

This is some "obfuscate things just for the heck of it" algorithm, from which very little of value can be learnt, except "don't write crap like this".这是一些“只是为了它而混淆事物”的算法,从中可以学到很少的价值,除了“不要像这样写废话”。

What it does is to decrease the value by 3, but split that decrease in two steps.它所做的是将值减少 3,但将减少分成两步。 First always decrease by 1 and then by 2 more, unless it's the very last lap in the loop.首先总是减少 1,然后再减少 2,除非它是循环的最后一圈。 So the && serves two purposes: to only decrease by 1 the last time of the iteration, as well as a sequence point to allow two modifications of x in the same expression (which is very bad practice, && or not).所以&&有两个目的:在最后一次迭代中只减少 1,以及允许在同一个表达式中对x进行两次修改的序列点(这是非常糟糕的做法, &&或不是)。

For those not participating in the International Obfuscated C Code Contest, it might make more sense to rewrite the code similar to this:对于那些没有参加国际混淆 C 代码竞赛的人来说,重写类似这样的代码可能更有意义:

int x;
for(x = -5; x >= -11; x -= 3)
{
  printf("%d, ", x);
}
printf("%d", x+2);

This is also nonsense code but at least it is readable.这也是无意义的代码,但至少它是可读的。 As a bonus, it also contains less branching than the obfuscated version.作为奖励,它还包含比混淆版本更少的分支。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM