【问题标题】:About the braces in a 'case' statement in 'switch'关于“switch”中“case”语句中的大括号
【发布时间】:2011-08-12 18:20:54
【问题描述】:

今天,当我尝试编写代码来仅对两个 2*2 矩阵进行加减运算时,我使用了 switch 语句,但出现错误:

在函数main()中绕过局部变量的初始化

代码

#include <iostream.h>
#include <conio.h>
#include <string.h>

int
main()
{
    int mat1[2][2], mat2[2][2], mat3[2][2];

    cout << "Enter the elements in the first matrix";
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            cin >> mat1[i][j];
        }
    }

    cout << "\n\nEnter the elements of the second matrix";

    for (int k = 0; k < 2; k++) {
        for (int l = 0; l < 2; l++) {
            cin >> mat2[k][l];
        }
    }

    cout << "\n\nsaved......";

    int choice;
    cout << "\n\n\nFor adding these two matrices,press 1";
    cout << "\nFor subtracting these two matrices,press 2";
    cin >> choice;

    switch (choice) {
    case 1:

        cout << "The addition of the two matrices will yield";
        for (int a = 0; a <= 1; a++) {
            for (int b = 0; b <= 1; b++) {
                mat3[a][b] = mat1[a][b] + mat2[a][b];
            }
        }
        break;

    case 2:
        cout << "The subtraction of the two matrices will yield";
        for (int c = 0; c <= 1; c++) {
            for (int d = 0; d <= 1; d++) {
                mat3[c][d] = mat1[c][d] - mat2[c][d];
            }
        }
        break;
    }
    getch();
    return 0;
}

我还发现我可以通过将 case(s) 的代码放入大括号中来消除此错误,现在,

  1. 我的困惑是关于error...
  2. &case....中大括号的要求

(我知道我没有使用新的编码约定,如&lt;iostream&gt;、std 命名空间等,因为我已经在Turbo C++ 编译器中编写了它,所以一个中肯的答案是谦虚地请求。)

【问题讨论】:

  • 哪一行代码产生了这个错误?
  • 这不是一个答案,但是 case 语句的两个分支都添加了两个矩阵,之后没有任何东西将它们打印出来。我猜这不是你的意思。
  • 粗体字没有告诉我们它指的是哪一行;看我的回答。

标签: c++ switch-statement case


【解决方案1】:

switch 语句只是一堆标签和一个goto,由编译器根据switch 测试中事物的值完成。

当函数中有一个局部变量时,在该变量声明之后的任何地方都可以使用它。例如:

int a;
// can use a now

但是,在switch 语句中,如果您有一个局部变量:

case a:
    int a;
    break;
case b:
    // we can use a here because these cases are just labels used in a goto
    // i.e. the cases do *not* create a new scope

因此,当您在 case 中有一个变量时,该变量存在于其下方的 cases 中,但该变量将不存在,因为初始化它的代码被 case 语句跳过。我很难解释,也许其他人可以做得更好。

大括号解决了这个问题,因为它们使变量成为局部变量,因此它在随后的cases 中不存在。仅当输入特定的case 时才会创建它,并且如果您忘记了break 并且控制权落入下一个case,则结尾} 会结束作用域并导致变量被销毁所以它不是可以从下一个case访问,不能跳过初始化。

所以请记住所有cases 共享范围。这可能有助于您理解这一点。

【讨论】:

  • 我在 OP 发布的代码中没有看到类似的情况。事实上,它可以在 gcc 上愉快地编译,ideone.com/tgpuT
  • @Als 是的,我知道,因为 for 循环中的变量范围是受控的,但我不知道如果没有这种情况,他如何得到该错误消息,所以我假设代码不是错误的来源,或者它不是真实的。
  • 因为他使用的是不符合标准的蹩脚的旧编译器。
  • @Als:公平地说,它可能符合当时存在的事实标准。我认为 Stroustrup 在“C++ 的设计与演进”中提到了这个问题。
【解决方案2】:

在重新缩进您的代码并更改一些内容以便它在我的系统上编译后,g++ 编译它而不发出警告。

我最好的猜测是它与 for 循环中声明的对象范围的旧规则有关(它曾经一直存在到封闭范围的末尾;在现代 C++ 中,它仅限于循环本身),但我不太确定。

为了帮助我们解决这个问题,请正确缩进代码,并向我们显示确切的错误消息,包括行号。如果错误显示“第 42 行:...”,请在您的源代码中添加注释,例如 // this is line 42

编辑:是的,我认为这就是问题所在。在现代 C++ 中,您的代码是可以的,因为循环变量的范围仅限于循环本身。显然 Turbo 实现了该语言的一个非常旧的版本,因此您的变量 a,例如,一直可见到 switch 语句的底部。将每个 for 循环括在花括号中应该可以避免警告:

{
    for (int a = 0; a <= 1; a++) {
        for (int b = 0; b <= 1; b++) {
            mat3[a][b] = mat1[a][b] + mat2[a][b];
        }
    }
}

EDIT2:或者更好的是,停止使用 Turbo C++ 并获得现代编译器。

EDIT3:编译器对此发出警告的原因是,即使看起来i 在使用前总是被初始化,原则上您可以在case 2: 部分引用i,绕过初始化。 (同样,这仅适用于旧规则。)

解决此问题的一种更简洁的方法可能是将每个 case 部分括在大括号中:

switch (choice) {
    case 1: {
        ...
        break;
    }
    case 2: {
        ...
        break;
    }
}

(或者,再次使用现代编译器,除非您有充分的理由坚持使用 Turbo C++)。

【讨论】:

  • 尊敬的先生,实际上在turbo c ++中没有办法这样做,..&错误消息与我在问题中以粗体显示的相同
  • 真的吗?它只是给您一条错误消息,而没有告诉您它抱怨的源代码中的哪一行?还是它会将您转储到编辑器中,光标位于违规行?如果有,是哪一行?
  • 仅突出显示文本“case 1:”
  • 我的+1,这是正确答案。请链接到this,这表明它可以与符合标准的编译器(如 gcc)一起使用。
  • 啊,是的,它可能是旧的 for 范围。哇,那是旧的。
【解决方案3】:

case 块本身并不是一个新范围。您在其中声明的任何变量对于switch 语句的其余部分都是可见的。但是在其他 case 块中,它是未初始化的。通过添加大括号,您创建了一个新范围,因此其他块无法看到它。

例如:

switch (choice)
{
case 0:
    int a = 42;
    break;


case 1:
    std::cout << a << std::endl; // 'a' is uninitialized here
    break;
}


switch (choice)
{
case 0:
    {
        int a = 42;
        break;
    }


case 1:
    std::cout << a << std::endl; // error -- 'a' is not declared here
    break;
}

我在您发布的代码中没有看到这样的情况,但这就是错误消息的含义。

【讨论】:

  • 你可能想链接到(这个)[ideone.com/tgpuT]gcc-4.3.4 显示没有错误。
  • @Als:你用 -Wall 试过了吗?
  • @Als:你的意思是here。那是OP的代码?正如我所说,我没有在该代码中看到这种情况。我认为我们没有看到有问题的代码或修复它的大括号。
猜你喜欢
  • 2018-05-05
  • 1970-01-01
  • 2011-11-14
  • 2021-11-28
  • 2023-03-20
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
相关资源
最近更新 更多