鱼C论坛

 找回密码
 立即注册
查看: 2490|回复: 16

[已解决]switch表达式中变量自增自减对标签的影响

[复制链接]
发表于 2017-10-15 14:16:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 小蒙 于 2017-10-15 14:16 编辑

个人理解:switch(i++)是一个完整表达式,完整表达式的结束是一个序列点,所以程序运行到第一个case的时候,i已经变成完成自增,那么,在i初始值是0的情况下,第一个case 0程序是进不去的,这时候i已经变成了1,和case 0不符。
通过调试,switch()确实是序列点,switch运行完后i的值确实递增了,但是同时,程序竟然能进入case 0,但是这时候i的值确实是1,这我就不懂了。

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <string.h>
  4. #include <iso646.h>
  5. #include <ctype.h>

  6. int main(void) {
  7.     int i = 0;
  8.     while (i < 3){
  9.         switch(i++){
  10.             case 0:
  11.                 printf("case 0\n");
  12.                 break;
  13.             case 1:
  14.                 printf("case 1\n");
  15.                 break;
  16.             case 2:
  17.                 printf("case 2\n");
  18.                 break;
  19.             default:
  20.                 printf("default\n");
  21.                 break;
  22.         }
  23.     }

  24.     return 0;
  25. }
  26. //结果如下
  27. case 0
  28. case 1
  29. case 2
复制代码
最佳答案
2017-10-15 15:49:41
小蒙 发表于 2017-10-15 15:17
在case0里面,并没有遇到i,但是i的值已经是1了。

是的,你要是在调试中单独看i的值的确是会增加的,但是在程序里你只有在switch中才出现了i,内部是没有的,但是内部判断的是 i 的值,只有在下一次出现 i 的时候才会改变值。我给你个程序,你可以试试看。
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         int i = 0, j;

  5.         j = i++;      // i++优先级肯定大于‘=’的吧,肯定是先运行i++再赋值吧
  6.         printf("i = %d\nj = %d\n", i, j);

  7.         return 0;
  8. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-10-15 14:51:36 | 显示全部楼层
没错呀,i++具有滞后性(我自己给的命名),就是说i++后呈现出的 i 的值还是以前的值,但是当下一次遇到 i 了才会显现出自增后的值,swich的时候虽然 i++ 了,但是 i=0,进入后先到case 0,但是到while判断的时候 i = 1,进入后到swich虽然i++,但是还是 i=1,就这样,一直到进入到case 2后,出去到while判断 i = 3,不循环,退出。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 15:14:37 | 显示全部楼层
swith(i++)相当于两句:

swith(i)
{
    ...
}

i++;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 15:17:11 | 显示全部楼层
本帖最后由 小蒙 于 2017-10-15 15:24 编辑
丶忘却的年少o 发表于 2017-10-15 14:51
没错呀,i++具有滞后性(我自己给的命名),就是说i++后呈现出的 i 的值还是以前的值,但是当下一次遇到 i  ...



                               
登录/注册后可看大图

在case0里面,并没有遇到i,但是i的值已经是1了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 15:24:52 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 14:51
没错呀,i++具有滞后性(我自己给的命名),就是说i++后呈现出的 i 的值还是以前的值,但是当下一次遇到 i  ...

重新传了图,麻烦看一下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 15:28:25 | 显示全部楼层
BngThea 发表于 2017-10-15 15:14
swith(i++)相当于两句:

swith(i)
  1. for(int i = 0; i++<5;)
  2.         printf("%d ", i);

  3.     return 0;
  4. //结果
  5. 1 2 3 4 5

  6. 如果switch是这样的话,那这个怎么理解?
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 15:34:27 | 显示全部楼层

这个在for循环中相当于for(int i=0;(i<5,i++);)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 15:43:43 | 显示全部楼层
BngThea 发表于 2017-10-15 15:34
这个在for循环中相当于for(int i=0;(i

那switch(i++)也相当于switch(i, i++)?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 15:49:41 | 显示全部楼层    本楼为最佳答案   
小蒙 发表于 2017-10-15 15:17
在case0里面,并没有遇到i,但是i的值已经是1了。

是的,你要是在调试中单独看i的值的确是会增加的,但是在程序里你只有在switch中才出现了i,内部是没有的,但是内部判断的是 i 的值,只有在下一次出现 i 的时候才会改变值。我给你个程序,你可以试试看。
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         int i = 0, j;

  5.         j = i++;      // i++优先级肯定大于‘=’的吧,肯定是先运行i++再赋值吧
  6.         printf("i = %d\nj = %d\n", i, j);

  7.         return 0;
  8. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 16:18:38 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 15:49
是的,你要是在调试中单独看i的值的确是会增加的,但是在程序里你只有在switch中才出现了i,内部是没有的 ...

c primer plus中有一个序列点和副作用的概念,完整表达式的结尾就是一个序列点,在这个点上所有副作用都在进入下一步之前发生,switch()是一个完整表达式,所以括号结尾就是一个序列点,在进入下一步case后,i的值本身的值肯定会增加(副作用),所以调试会发现i的值是1;但是如你所说,如果i++之后不明确出现i的调用,那么程序使用i的值还是旧值,就像j = i++;中j的值比i要小一样,可惜c primer plus中并没有提及这种特殊情况,多谢多谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 16:22:08 | 显示全部楼层
小蒙 发表于 2017-10-15 16:18
c primer plus中有一个序列点和副作用的概念,完整表达式的结尾就是一个序列点,在这个点上所有副作用都 ...

我没看过那本书,我也刚学没多久,但是代码练习做多了,慢慢的就知道了这个东西,而且视频里也有提到。我个人看书有点看不进去,就没怎么看书
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2017-10-15 16:26:01 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 16:22
我没看过那本书,我也刚学没多久,但是代码练习做多了,慢慢的就知道了这个东西,而且视频里也有提到。我 ...

多谢!@
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 16:37:59 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 16:22
我没看过那本书,我也刚学没多久,但是代码练习做多了,慢慢的就知道了这个东西,而且视频里也有提到。我 ...

还有一个关于goto的问题,我就不开帖了。
  1. if (a < b) {
  2.         goto x;
  3.     }
  4.     x:
  5.     printf("i am x\n");
复制代码


为什么不管 a < b 成立与否,标号x对应的printf语句都会执行,感觉不符合逻辑啊?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 17:03:27 | 显示全部楼层
小蒙 发表于 2017-10-15 16:37
还有一个关于goto的问题,我就不开帖了。

为什么不管 a < b 成立与否,标号x对应的printf语句都会执行 ...

你理解错了,如果 if 条件成立会执行 if 里的语句,但是内部语句刚好有是跳到 x 这个标号的语句执行;那么如果 if 不成立就跳过内部语句,执行后面的语句,但是好巧不巧,后面的语句就是 x 这个标号的语句,那么这么看来,不管 if 成立与否都会执行 x 标号的语句了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-15 17:15:38 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 17:03
你理解错了,如果 if 条件成立会执行 if 里的语句,但是内部语句刚好有是跳到 x 这个标号的语句执行;那 ...

给我感觉,这种写法应该是只有当程序由goto“跳到”标号x这里,那x后面的printf才会打印。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-15 19:23:46 | 显示全部楼层
小蒙 发表于 2017-10-15 17:15
给我感觉,这种写法应该是只有当程序由goto“跳到”标号x这里,那x后面的printf才会打印。。。

哈哈,其实不是这样的,就是一个标号,就像调试时候的断点一个意思。goto基本不用,尽量少用,跳来跳去容易出错。而且跳出去回不来,要么就再加一个goto跳回来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-19 17:44:35 | 显示全部楼层
丶忘却的年少o 发表于 2017-10-15 19:23
哈哈,其实不是这样的,就是一个标号,就像调试时候的断点一个意思。goto基本不用,尽量少用,跳来跳去容 ...


你好,我开了一个新帖子,有关于文件结束符和被getchar()读取后又放回队列导致无限循环的问题,能否帮忙看一下,谢谢。http://bbs.fishc.com/thread-98080-1-1.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-19 10:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表