switch 和 while 递增和求值的区别

Difference between switch and while increment and evaluate

如果i等于1,在这条语句之后,

while (i++ <= 10){} 

i 被视为 2,即在块中评估之前递增。

但是如果用在switch中,

switch(i++){} 

i 在块中递增之前得到评估。

为什么这些案例 i++ 表现不同?

示例:

While 案例:

#include <stdio.h>

int main()
{
    int age = 20;

    while (age++ <= 65)
    {
        if ((age % 20) == 0)
        {
            printf("You are %d years old\n", age);
        }       
    }

    return 0;
}

我希望打印出来:

You are 20 years old
You are 40 years old
You are 60 years old

开关盒:

#include <stdio.h>

int main()
{
 int i = 0;

 while (i < 3)
 {
     switch (i++)
     {
         case 0:printf("print 0");
         case 1:printf("print 1");
         case 2:printf("print 2");
         default:printf("Oh no!");
     }
     putchar('\n');
 }

 return 0;
}

有了这个

while (i++ <= 10){} 

发生以下情况:

  • i 从 1 开始
  • i(为一)与 10
  • 进行比较
  • i 增加到 2
  • 块被执行,其中 i 为 2

有趣的是,如果 i 以 10 开始,while 循环将再次执行,此时 i 为 11。

有了这个:

switch(i++){}
  • i 开始为 1
  • 根据“1”选择要执行的case
  • i 增加到 2
  • 执行“1”的情况,i 为“2”

不,这不可能。

在这两种情况下,值的递增,post-递增运算符的副作用发生在结果的值计算之后。

引用 C11,章节 §6.5.2.4,(强调我的

The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it).[...] The value computation of the result is sequenced before the side effect of updating the stored value of the operand. [...]

详细说明

  • while (i++ <= 10)的情况下,i的值在递增之前用于验证循环条件。

  • switch(i++){}的情况下,i的值在增量之前用于跳转到特定情况。未修改的(尚未)值用作控制表达式的值,并且在对控制表达式求值之后,发生增量。

补充一下,如果您尝试在其中一个 case 语句中打印 i 的值(例如,case 1:),您可以看到它实际上增加了。

事实上,这两种情况实际上是一样的:原始值用于比较,它递增并执行块。看下面的代码:

#include <stdio.h>

int main() {
    int i=1;

    switch(i++) {
    case 1:
        printf("Case 1: %d\n", i);
        break;
    default:
        printf("Not 1: %d\n", i);
    }
    return 0;
}

它的输出是:

Case 1: 2

这证明 i 在 块被评估之前 已经递增。

while 循环将不会打印 You are 20 years old,因为变量在执行循环体之前递增。它开始为 age = 20。第一个

while (age++ <= 65)

测试是否20 <= 65,所以进入循环。然后它递增 age,因此在循环内部它是 age = 21。结果,测试 if (age % 20 == 0) 不会成功,您也不会收到消息 You are 20 years old.

其他 20 的倍数在循环的未来迭代中仍然打印。