Reputation: 1322
I ran into an error recently where a variable was initialized inside a switch statement. I started playing around with this more and realize I don't know the first thing about what GCC is trying to do in some of these optimizations.
int main(int argc, char** argv) {
switch (argc) {
case 1000: return 42;
int y = 24;
default: return y;
}
return argc;
}
The generated code always returns 42. What is going on? Why does the int y = 24
muck everything up?
$ gcc -Wall -Werror -O2 -c test.c
$ objdump -drwCS -Mintel test.o
testo.o: file format elf64-x86-64
Disassembly of section .text.startup:
0000000000000000 <main>:
0: b8 2a 00 00 00 mov eax,0x2a
5: c3 ret
Upvotes: 6
Views: 130
Reputation: 213822
Cases in a switch
are to be regarded as labels. If we translate your code to the equivalent goto-spaghetti, it might be easier to understand:
int main(int argc, char** argv)
{
if(argc == 1000)
goto label_1000;
else
goto label_default;
label_1000: return 42;
int y = 24;
label_default: return y;
return argc;
}
The goto label_default
jumps past the label initialization of y
and so it doesn't necessarily get executed. The same thing happens in your switch.
Best practice when declaring variables inside switches is therefore to always use a compound statement per case:
case 1000:
{
int y = 24;
break;
}
Apart from preventing spaghetti bugs, this also reduces the scope of the variable to the specific case
.
Upvotes: 4
Reputation: 854
int main(int argc, char** argv) {
switch (argc) {
case 1000: return 42;
int y = 24;
default: return y;
}
return argc;
}
To explain this a bit more, a switch doesn't exactly do a linear progression. The logic equivalent to this would be:
"If argc is 1000, return 42. Otherwise return y"
The int y = 24;
is never used since it's never reached, the compiler can optimize this out, and since there's UB in the case of a default, it might as well return 42.
To fix this and behave the way I suspect you intend, you just need to declare y
outside of the switch statement.
int main(int argc, char** argv) {
int y = 24;
switch (argc) {
case 1000: return 42;
default: return y;
}
return argc;
}
Upvotes: 4