小蒙 发表于 2017-10-15 14:16:47

switch表达式中变量自增自减对标签的影响

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

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

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <iso646.h>
#include <ctype.h>

int main(void) {
    int i = 0;
    while (i < 3){
      switch(i++){
            case 0:
                printf("case 0\n");
                break;
            case 1:
                printf("case 1\n");
                break;
            case 2:
                printf("case 2\n");
                break;
            default:
                printf("default\n");
                break;
      }
    }

    return 0;
}
//结果如下
case 0
case 1
case 2

丶忘却的年少o 发表于 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,不循环,退出。

BngThea 发表于 2017-10-15 15:14:37

swith(i++)相当于两句:

swith(i)
{
    ...
}

i++;

小蒙 发表于 2017-10-15 15:17:11

本帖最后由 小蒙 于 2017-10-15 15:24 编辑

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

https://i.loli.net/2017/10/15/59e30d1ce217e.jpeg

在case0里面,并没有遇到i,但是i的值已经是1了。

小蒙 发表于 2017-10-15 15:24:52

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

重新传了图,麻烦看一下。

小蒙 发表于 2017-10-15 15:28:25

BngThea 发表于 2017-10-15 15:14
swith(i++)相当于两句:

swith(i)


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

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

如果switch是这样的话,那这个怎么理解?

BngThea 发表于 2017-10-15 15:34:27

小蒙 发表于 2017-10-15 15:28


这个在for循环中相当于for(int i=0;(i<5,i++);)

小蒙 发表于 2017-10-15 15:43:43

BngThea 发表于 2017-10-15 15:34
这个在for循环中相当于for(int i=0;(i

那switch(i++)也相当于switch(i, i++)?

丶忘却的年少o 发表于 2017-10-15 15:49:41

小蒙 发表于 2017-10-15 15:17
在case0里面,并没有遇到i,但是i的值已经是1了。

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

int main(void)
{
        int i = 0, j;

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

        return 0;
}

小蒙 发表于 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中并没有提及这种特殊情况,多谢多谢。

丶忘却的年少o 发表于 2017-10-15 16:22:08

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

我没看过那本书,我也刚学没多久,但是代码练习做多了,慢慢的就知道了这个东西,而且视频里也有提到。我个人看书有点看不进去,就没怎么看书{:10_262:}

小蒙 发表于 2017-10-15 16:26:01

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

多谢!@

小蒙 发表于 2017-10-15 16:37:59

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

还有一个关于goto的问题,我就不开帖了。if (a < b) {
      goto x;
    }
    x:
    printf("i am x\n");

为什么不管 a < b 成立与否,标号x对应的printf语句都会执行,感觉不符合逻辑啊?

丶忘却的年少o 发表于 2017-10-15 17:03:27

小蒙 发表于 2017-10-15 16:37
还有一个关于goto的问题,我就不开帖了。

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

你理解错了,如果 if 条件成立会执行 if 里的语句,但是内部语句刚好有是跳到 x 这个标号的语句执行;那么如果 if 不成立就跳过内部语句,执行后面的语句,但是好巧不巧,后面的语句就是 x 这个标号的语句,那么这么看来,不管 if 成立与否都会执行 x 标号的语句了。

小蒙 发表于 2017-10-15 17:15:38

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

给我感觉,这种写法应该是只有当程序由goto“跳到”标号x这里,那x后面的printf才会打印。。。

丶忘却的年少o 发表于 2017-10-15 19:23:46

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

哈哈,其实不是这样的,就是一个标号,就像调试时候的断点一个意思。goto基本不用,尽量少用,跳来跳去容易出错。而且跳出去回不来,要么就再加一个goto跳回来

小蒙 发表于 2017-10-19 17:44:35

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

你好,我开了一个新帖子,有关于文件结束符和被getchar()读取后又放回队列导致无限循环的问题,能否帮忙看一下,谢谢。http://bbs.fishc.com/thread-98080-1-1.html
页: [1]
查看完整版本: switch表达式中变量自增自减对标签的影响