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 的倍数在循环的未来迭代中仍然打印。
如果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 的倍数在循环的未来迭代中仍然打印。