I had code structured something like (greatly simplified by way of example):
void MyFunction()
{
int a = GetValueOfA();
switch(a)
{
case 1:
int b = 2;
DoSomething(b);
break;
case 2:
int c = 3;
DoSomethingElse(c);
break;
}
}
This gave me an error on the second case "error C2360: initialization of 'b' is skipped by 'case' label." *What?!? This is one of those cases where the message is technically accurate after you understand what it says but utterly useless to explain what is going on or what the solution is at first glance. Or perhaps I'm slow. I stared at this for a bit before I comprehended what it was trying to tell me.
The root of the issue is that, while the case statements appear to be in their own scope, they aren't. (I'm sure I knew this at some point, but the memory was overridden long ago. Or perhaps I have too many languages floating around in my head.) The scope for variables inside a switch statement is all the cases, not just the current case. Therefore, in the code above, variables b and c are available anywhere inside the switch statement. The error says b is defined, but may not be initialized properly, when a = 2.
All the solutions involve changing the scope of b and c. There are a couple immediately obvious solutions:
1) Put braces around the contents of the case statements to limit their scope.
void MyFunction()
{
int a = GetValueOfA();
switch(a)
{
case 1:
{
int b = 2;
DoSomething(b);
}
break;
case 2:
{
int c = 3;
DoSomethingElse(c);
}
break;
}
}
2) Put the contents of the case statements in their own functions, another way of limiting their scope.void PerformCase1()
{
int b = 2;
DoSomething(b);
}
void PerformCase2()
{
int c = 3;
DoSomethingElse(c);
}
void MyFunction()
{
int a = GetValueOfA();
switch(a)
{
case 1:
PerformCase1();
break;
case 2:
PerformCase2();
break;
}
}
3) Move the declaration to before the switch statement and don't do initialization/declaration on the same line.void MyFunction()
{
int b, c;
int a = GetValueOfA();
switch(a)
{
case 1:
b = 2;
DoSomething(b);
break;
case 2:
c = 3;
DoSomethingElse(c);
break;
}
}
Another option would be to change the structure of the code such that the switch isn't necessary. In general, this would be my favored solution although in this specific case of legacy code, that would have involved more work than the budget allowed.* Actually my notes say I also got a second error on the switch stating "transfer of control bypasses initialization of variable b" but I could not reproduce this one. Perhaps I simplified too much. Or perhaps it was a different version of the compiler. Or perhaps different option settings. Or something else entirely.
No comments:
Post a Comment
Comments are welcome but I do moderate them. This is simply to keep things wholesome for general family viewing. By default, comments will be accepted. The few things that will cause a comment to be rejected are:
1. It is too long even though it may be well-written and make interesting points. It's supposed to be a comment, not an essay. If you have that much to say, write a blog article and backlink to me.
2. It is nasty, impolite or uses language that is unacceptable.
3. It includes a a link that has a typo or is broken in some other way.
4. It should have been sent as an e-mail since it is clearly addressed to me and does not appear to have been intended for other readers.
5. It is blatantly self-promotional. This does not mean it can't be self-promotional at all, but it should add some value over an above the marketing.