Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About the braces in a 'case' statement in 'switch'

Today, while I was trying to write code to just add and subtract the two 2*2 matrices, in which I used a switch statement, I got an error:

case bypass initialization of local variable in function main()

Code

#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;
}

I also found that I can take the rid of this error by placing the code of case(s), into braces, NOW,

  1. my confusion is about the error...
  2. & the requirement of braces in case....

(I know I haven't used the new coding conventions, like <iostream>, std namespace, etc., etc. as I have written it in the Turbo C++ compiler, so a to-the-point answer is humbly requested.)

like image 373
nobalG Avatar asked Aug 12 '11 18:08

nobalG


2 Answers

A switch statement is just a bunch of labels and a goto done by the compiler depending on the value of the thing inside the switch test.

When you have a local variable in a function, anywhere past the declaration of that variable you can use it. For instance:

int a;
// can use a now

However, in a switch statement, if you have a local variable:

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

So when you have a variable in a case, the variable exists in cases below it but the variable won't exist because the code that initialized it got skipped by the case statement. It's hard for me to explain, maybe someone else can do a better job.

The braces fix this problem because they make the variable local, so that it doesn't exist in subsequent cases. It only gets created if that particular case gets entered, and if you forget a break and control falls through to the next case, the ending } ends the scope and causes the variable to be destroyed so it's not accessible from the next case, and the initialization can't be skipped.

So just remember that all the cases share scope. That might help you understand this.

like image 179
Seth Carnegie Avatar answered Sep 16 '22 14:09

Seth Carnegie


After re-indenting your code and changing a few things so it compiles on my system, g++ compiles it without warnings.

My best guess is that it has something to do with the old rules for the scope of an object declared in a for loop (it used to live until the end of the enclosing scope; in modern C++ it's limited to the loop itself), but I can't quite be sure.

To help us figure this out, please indent the code properly, and show us the exact error message, including the line number. If the error says "line 42: ...", add a comment in your source like // this is line 42.

EDIT: Yes, I think that's the problem. In modern C++, your code is ok, because the loop variables are scoped to the loops themselves. Apparently Turbo implements a very old version of the language, so your variable a, for example, is visible all the way to the bottom of the switch statement. Enclosing each for loop in curly braces should avoid the warning:

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

EDIT2: Or better yet, stop using Turbo C++ and get a modern compiler.

EDIT3: And the reason that compiler warns about this is that even though it appears that i is always initialized before use, you could in principle refer to i in the case 2: section, bypassing the initialization. (Again, this only applies under the old rules.)

A cleaner way to work around this is probably to enclose each case section in braces:

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

(or, again, get a modern compiler, unless you have a really good reason to stick with Turbo C++).

like image 21
Keith Thompson Avatar answered Sep 19 '22 14:09

Keith Thompson