• Switch-case 内定义变量的问题


    Switch-case 内定义变量的问题

    这个问题需要分开讨论,C 语言和 C++ 的标准定义是不同的。

    C++

    int Caset(int a) {
        switch (a) {
            case 1:
                int b = 1;
                std::cout<<"a==1: "<<b<<std::endl;
                break;
            case 2:
                b = 2;
                std::cout<<"a==2: "<<b<<std::endl;
                break;
        }
    }
    

    编译报错信息为

    simple.cc:35:9: error: cannot jump from switch statement to this case label
            case 2:
            ^
    simple.cc:32:17: note: jump bypasses variable initialization
                int b = 1;
                    ^
    

    也就是说,跳到 case2 的这个地方,忽略了对于 b 这个变量的初始化,这个很直观,就是在这里我找不到 b。

    那么如果改成

    int Caset(int a) {
        switch (a) {
            case 1:
                int b;
                b = 1;
                std::cout<<"a==1: "<<b<<std::endl;
                break;
            case 2:
                b = 2;
                std::cout<<"a==2: "<<b<<std::endl;
                break;
        }
    }
    

    顺利成功,没有报错,如果 a 为 2,那么输出 b 也是 2,说明逻辑没有问题。那么问题来了,b 在前面声明,为什么后面可以用到呢,因为 switch-case 的逻辑控制就是用 label 来标记跳转的,而不是别的复杂的逻辑控制,所以 b 的作用域是在整个 switch 的花括号内,关于这个问题见知乎讨论请教switch内部的变量定义问题

    C 语言

    上面两种写法统统出错,

    void Caset(int a) {
        switch (a) {
            case 1:
                /* one style */
                int b;
                b = 1;
                
                /* another style */
                int b = 1;
    
                printf("1: %d", b);
                break;
            case 2:
                b = 2;
                printf("2: %d", b);
                break;
        }
    }
    

    两种写法都错

    First style:

    main.c:12:13: error: expected expression
            int b; 
            ^
    main.c:13:13: error: use of undeclared identifier 'b'
            b = 1;
            ^
    

    Another style:

    ttt.c:11:13: error: expected expression
            int b = 1;
            ^
    

    意思是说,此处需要一个表达式(expression),而不是一个变量声明初始化。有一个很黑客的做法,如下:

    void Caset(int a) {
        switch (a) {
            case 1:
                ; 
                int b = 1;
                // b = 1;
    
                printf("1: %d 
    ", b);
                break;
            case 2:
                b = 2;
                printf("2: %d 
    ", b);
                break;
        }
    }
    

    这个很不能理解了,其实也就是说保证 case 后面跟着的确实是 expression 即可。考虑一下 C++ 代码出现的问题:跳过变量的声明?C 语言中同样跳过,但是编译器不认为这个是错误,而且逻辑上面也是没有问题的,在后面的 case 中可以正常给变量赋值,但是如果 case2 中,我不是给 b 赋值,而是直接访问 b,那返回的数值就是一个随机的错误的数据了,我在我的电脑上使用 gcc 编译,若直接读取数据,得到的是 0,当然编译通过,连警告都没有。

    总结起来就是:

    1. C 编译器允许一个 case 使用另一个 case 后声明定义的变量,但是 C++ 语法不允许这个
    2. C 不允许 case 后面紧跟声明或定义,只允许表达式(expression); C++ 对这个没有限制

    通用解法

    当然我认为这样的代码可读性差,比较好的做法可以是将声明变量的事情放在头上做。

    void Caset(int a) {
        switch (a) {
            int b;
            case 1:
                b = 1;
                // b = 1;
                printf("1: %d 
    ", b);
                break;
            case 2:
                b = 2;
                printf("2: %d 
    ", b);
                break;
        }
    }
    

    但是要留心, switch 和 case 之前那块地方也就只能写写这样的声明,写别的表达式,赋值啊什么的,统统是不会生效的


    参考:

    Why can't variables be declared in a switch statement?这个链接中我个人比较推荐 AnT 的回答,讲清楚了问题的原因和解决方案的原理

  • 相关阅读:
    7.12-7.19 id、w、who、last、lastb、lastlog
    查询登录信息 w, who*, id, tty, last, finger
    [rhel-media] :Yum软件仓库唯一标识符,避免与其他仓库冲突。
    :整数 跳转到该行 Vim中常用的命令
    spec2006与spec2000的对比简要说明
    Linux性能监控与分析之--- CPU
    Android实现登录小demo
    python学习笔记——旧类与新类继承中的构造函数
    tair ldb存储引擎性能測试方案
    串口通讯方式1编程
  • 原文地址:https://www.cnblogs.com/psklf/p/6702767.html
Copyright © 2020-2023  润新知