case "wrong list": what happens? - c++

I'm a newbie in C++. As fas as I know, something like
switch(ival)
{
case 1,2,3:
/* do something */
/* other case selections */
}
is wrong. The correct way is to write:
switch(ival)
{
case 1: case 2: case 3: // in multiple lines if you prefer
/* do something */
/* other case selections */
}
That said (hoping it's correct), what happens when you compile the first? Visual Studio intellisense detects an error, but the program compiles fine.
I experimented a bit and I was betting that he would execute "do something" if ival was 1, but not if it was 2 or 3. I've setup multiple case statement like that, everyone with its own control variable to keep track of the execution, but nothing seems to happen as they all keep initialization values through the end of the program.
I'm puzzled. Anyone knows what happens behind the curtain?

When the compiler sees a case statement case N it will always interpret N as an integer. In this case, your compiler is evaluating the expression 1,2,3 as 3. Your /* do something */ code is only executed when ival is 3. (Tested with MSVS2015).
As you noted, this expression isn't the right way to express that you want multiple cases to be handled by the same code, and you should expect other compilers to handle the situation differently.

Related

How do jump-tables work?

In the following document, pages 4-5:
http://www.open-std.org/jtc1/sc22/wg21/docs/ESC_Boston_01_304_paper.pdf
typedef int (* jumpfnct)(void * param);
static int CaseError(void * param)
{
return -1;
}
static jumpfnct const jumptable[] =
{
CaseError, CaseError, ...
.
.
.
Case44, CaseError, ...
.
.
.
CaseError, Case255
};
result = index <= 0xFF ? jumptable[index](param) : -1;
it is comparing IF-ELSE vs SWITCH and then introduces this "Jump table". Apparently it is the fastest implementation of the three. What exactly is it? I cannot see how it could work??
The jumptable is a method of mapping some input integer to an action. It stems from the fact that you can use the input integer as the index of an array.
The code sets up an array of pointers to functions. Your input integer is then used to select on of these function-pointers. Generally, it looks like it's going to be a pointer to the function CaseError. However, every now and again, it will be a different function that is being pointed to.
It's designed so that
jumptable[62] = Case62;
jumptable[95] = Case95;
jumptable[35] = Case35;
jumptable[34] = CaseError; /* For example... and so it goes on */
Thus, selecting the right function to call is constant time... with the if-elses and selects, the time taken to select the correct function is dependent on the input integer... assuming the compiler doesn't optimize the select to a jumptable itself... if it's for embedded code, then there's a chance that optimizations of this kind have been disabled... you'd have to check.
Once the correct function-pointer is found, the last line simply calls it:
result = index <= 0xFF ? jumptable[index](param) : -1;
becomes
result = index <= 0xFF /* Check that the index is within
the range of the jump table */
? jumptable[index](param) /* jumptable[index] selects a function
then it gets called with (param) */
: -1; /* If the index is out of range, set result to be -1
Personally, I think a better choice would be to call
CaseError(param) here */
Jumpfnct is a pointer to a function. Jumptable is an array that consists of a number of jumpfncts. The functions can be called just by referencing their position in the array.
For example, jumptable0 will execute the first function, passing along param. jumptable1 will execute the second function, etc.
If you don't know about function pointers, you shouldn't use this trick. They're very handy, in a narrow domain.
It's very fast and space efficient, when what you're doing is switching between a large number of similar function calls. You are adding a function call overhead that a switch statement doesn't necessarily have, so it might not be appropriate in all circumstances. If your code is something like this:
switch(x) {
case 1:
function1();
break;
case 2:
function2();
break;
...
}
A jump table might be a good substitution. If, though, your switch is something like this:
switch(x) {
case 1:
y++;
break;
case 1023:
y--;
break;
...
}
It probably wouldn't be worth doing.
I've used them in a toy FORTH language interpreter, where they were invaluable, but in most cases you're not going to see a speed benefit that makes them worth using. Use them if it makes the logic of your program clearer, not for optimization.
This jumptable returns a pointer-to-function by its index. You define this table in a way that invalid indexes point to the function that returns some invalid code (like -1 in the example) and valid indexes point to the functions you need to call.
Construction
jumptable[index]
returns pointer-to-function and this function gets called
jumptable[index](param)
where param is some custom parameter.
A Jump-Table is an obvious, but rarely used optimization, that for some reason seems to have fallen out of favor.
Briefly, instead of testing a value and exiting out of a switch/case or if-else block to branch to function or code path, you create an array which is filled with the addresses of the functions the program can branch to.
Once completed, this arrangement eliminates the relentless if testing attendant with if-else and switch/case blocks. The code uses the variable that would otherwise be tested with if as a subscript into the function-pointer array, and proceeds directly the the appropriate code - sans ANY if testing. A perfectly efficient branch. The assembly code should literally be a jump.
If you profile code, and find a hot-spot where the program is spending a large % of it's time, look to this kind of optimization to improve performance. A little bit of this can go a long way if it's part of a code's hot-spot.
Thanks for the link. Nice find!
As mentioned in the comment above, whether this solution is more or less effiicent than, for example, a switch statement depends on the amount of work needed to be done for each case.
Writing a regular switch statement for the values you want to process will definitely be a clearer way to see what the code does. So unless either space or speed requirements dictate that a more sophisticated solution, I would suggest that this is not a "better" solution.
Tables of function pointers is however an efficient and good way to solve certain problems. I use function pointers in a table quite regularly to do things like "Benchmark 11 different solutions to a problem", where I have a struct wiht the name of the function and the function, and some parameters perhaps. Then I have one function to time and loop over the code a few million times (or whatever it takes to get a long enough measurement to make sense)

Turn off compiler warning for switch/case statements using enums

Let's say you have an enumeration type with 50+ entries for its value. There have been times where I've switch/cased an enum value with this amount of entries before, but only to check for, say, anywhere from 2 to 5 entries out of this.
For example, OpenGL sticks the majority of its enumerations in one enum type, referred to as GLenum. These values range from GL_VERTEX_SHADER to GL_STREAM_DRAW to GL_TRIANGLES to GL_ARRAY_BUFFER, etc.
As you can see, while these are related in terms of a bigger picture, the context in which they would be used does not relate with one another.
I've generated warnings on MinGW/GCC in Linux, where each warning accounts for every enum value listed in its type declaration. I'm not sure if this happens on VC++, but I figured I'd account for it anyway just in case.
In other words, the amount of warnings generated is TotalEnumValues - AmountOfCaseStatements for each enum value, providing not all enumerations have been accounted for in the statement itself, which can easily lead to 100+ compiler warnings if your enumeration type contains at least 100 entries.
I've often used if/else to accommodate this, but when checking enum values for more than just one entry (which is honestly quite rare, since the purpose of enums in general requires conditional logic to compliment it), I've always been prone to using switch/case, since I find it more aesthetically pleasing (even if it just compiles into an if/else statement anyway ;) )
So, is this warning possible to turn off? If so, how?
Add a default: case that does nothing. The compiler will see that you are "handling" all the possibilities (thus removing the warning) but it won't change at all the generated code if you don't specify any action for it.
To clarify: I'm talking about this:
switch(a)
{
case CONSTANT_1:
...
break;
case CONSTANT_2:
...
break;
}
vs this:
switch(a)
{
case CONSTANT_1:
...
break;
case CONSTANT_2:
...
break;
default:
}
the second one does not modify at all the behavior, so the compiler shouldn't change the generated code, but will tell it that you didn't forget about the other (im)possible cases.

Switch inside For loop - Getting weird results in Release mode

Is there anything speaking against a structure like to following. In Release mode, Visual Studio seems to ignore i < 10 and execute the loop without end. If I set a break point I see that i runs from 0 to 9 and stays at 9 in all further iterations. If I printf i, I get a error after the 10 iteration, because arr only has 10 fields. Very strange. Please help.
for (i = 0; i < 10; i++){
switch (arr[i].type1){
case A:
//something
break;
case B:
switch (arr[i].type2){
//something
}
break;
default:
break;
}
}
Thanks!
EDIT: I removed all switch statements and replaced them with if statements. Work perfectly now. I still have difficulty believing that I was right and Visual Studio wrong. What about all my other Switch statements in the program? :/
I suspect that
// something
might have something to do with it. If you run this code as is (with the actual case code removed) -- does it happen?
How about if you take the entire switch and put it in a function?
You might be changing i somewhere in that // something either directly, or by some memory bounds issue.
nothing wrong with your example. Perhaps you have some accidental stack-overwriting or something like that in other parts of your code that introduce weird side effects in that place (and no sense making debugging sessions)?
Change the loop variable to j and make the first line of the loop:
int i = j;
Does it still do it?
As long as I don't know what // something does, I'll just give you the best idea I have given what I know;
If this only occurs in release mode, I would guess that the optimization done by the compiler may be the cause if this odd behaviour.
If you can make this occur reliably with the exact code given above, I'd say you should try turning off optimization and see if that helps.

How to store goto labels in an array and then jump to them?

I want to declare an array of "jumplabels".
Then I want to jump to a "jumplabel" in this array.
But I have not any idea how to do this.
It should look like the following code:
function()
{
"gotolabel" s[3];
s[0] = s0;
s[1] = s1;
s[2] = s2;
s0:
....
goto s[v];
s1:
....
goto s[v];
s2:
....
goto s[v];
}
Does anyone have a idea how to perform this?
It is possible with GCC feature known as "labels as values".
void *s[3] = {&&s0, &&s1, &&s2};
if (n >= 0 && n <=2)
goto *s[n];
s0:
...
s1:
...
s2:
...
It works only with GCC!
goto needs a compile-time label.
From this example it seems that you are implementing some kind of state machine. Most commonly they are implemented as a switch-case construct:
while (!finished) switch (state) {
case s0:
/* ... */
state = newstate;
break;
/* ... */
}
If you need it to be more dynamic, use an array of function pointers.
There's no direct way to store code addresses to jump to in C.
How about using switch.
#define jump(x) do{ label=x; goto jump_target; }while(0)
int label=START;
jump_target:
switch(label)
{
case START:
/* ... */
case LABEL_A:
/* ... */
}
You can find similar code produced by every stack-less parser / state machine generator.
Such code is not easy to follow so unless it is generated code or your problem is most
easily described by state machine I would recommend not do this.
could you use function pointers instead of goto?
That way you can create an array of functions to call and call the appropriate one.
In plain standard C, this not possible as far as I know. There is however an extension in the GCC compiler, documented here, that makes this possible.
The extension introduces the new operator &&, to take the address of a label, which can then be used with the goto statement.
That's what switch statements are for.
switch (var)
{
case 0:
/* ... */
break;
case 1:
/* ... */
break;
default:
/* ... */
break; /* not necessary here */
}
Note that it's not necessarily translated into a jump table by the compiler.
If you really want to build the jump table yourself, you could use a function pointers array.
You might want to look at setjmp/longjmp.
You can't do it with a goto - the labels have to be identifiers, not variables or constants. I can't see why you would not want to use a switch here - it will likely be just as efficient, if that is what is concerning you.
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
Optimizing compilers (including GCC) will compile a switch statement into a jump table (making a switch statement exactly as fast as the thing you're trying to construct) IF the following conditions are met:
Your switch cases (state numbers) start at zero.
Your switch cases are strictly increasing.
You don't skip any integers in your switch cases.
There are enough cases that a jump table is actually faster (a couple dozen compare-and-gotos in the checking-each-case method of dealing with switch statements is actually faster than a jump table.)
This has the advantage of allowing you to write your code in standard C instead of relying on a compiler extension. It will work just as fast in GCC. It will also work just as fast in most optimizing compilers (I know the Intel compiler does it; not sure about Microsoft stuff). And it will work, although slower, on any compiler.

Why the switch statement and not if-else?

I've been wondering this for some time now. I'm by far not a hardcore programmer, mainly small Python scripts and I've written a couple molecular dynamics simulations. For the real question: What is the point of the switch statement? Why can't you just use the if-else statement?
Thanks for your answer and if this has been asked before please point me to the link.
EDIT
S.Lott has pointed out that this may be a duplicate of questions If/Else vs. Switch. If you want to close then do so. I'll leave it open for further discussion.
A switch construct is more easily translated into a jump (or branch) table. This can make switch statements much more efficient than if-else when the case labels are close together. The idea is to place a bunch of jump instructions sequentially in memory and then add the value to the program counter. This replaces a sequence of comparison instructions with an add operation.
Below are some extremely simplified psuedo-assembly examples. First, the if-else version:
// C version
if (1 == value)
function1();
else if (2 == value)
function2();
else if (3 == value)
function3();
// assembly version
compare value, 1
jump if zero label1
compare value, 2
jump if zero label2
compare value, 3
jump if zero label3
label1:
call function1
label2:
call function2
label3:
call function3
Next is the switch version:
// C version
switch (value) {
case 1: function1(); break;
case 2: function2(); break;
case 3: function3(); break;
}
// assembly version
add program_counter, value
call function1
call function2
call function3
You can see that the resulting assembly code is much more compact. Note that the value would need to be transformed in some way to handle other values than 1, 2 and 3. However, this should illustrate the concept.
Switch can be optimized by compiler - you will get faster code.
Also I find it to be more elegant when dealing with enumerable types.
To sum up switch statement gives you performance + code elegance :)
Here are some useful links:
speed comparison of switch vs if/else in C#
Feedback-Guided Switch Statement
Optimization (pdf describing switch statement optimization)
I'm ignoring this type of low level optimization as usually unimportant, and probably different from compiler to compiler.
I'd say the main difference is readability. if/else is very flexible, but when you see a switch you know right away that all of the tests are against the same expression.
For expressiveness, the switch/case statement allows you to group multiple cases together, for example:
case 1,2,3: do(this); break;
case 4,5,6: do(that); break;
For performance, compilers can sometimes optimize switch statements into jump tables.
Besides the other mentioned Code readability and optimisation in .NET you also get the ability to switch on enums etc
enum Color { Red, Green, Blue };
Color c = Color.Red;
switch (c) // Switch on the enum
{
// no casting and no need to understand what int value it is
case Color.Red: break;
case Color.Green: break;
case Color.Blue: break;
}
The ability to fall through several cases (intentionally leaving out the break statement) can be useful, and as a few people have already said it's faster as well. Perhaps the most important and least important consideration though, is that it just makes for prettier code than if/else. :)
Switch can be optimized "Better" by some compilers. There are pitfalls with using the switch statement in certain languages. In Java, the switch cannot handle strings and in VB2005 the switch statement will not work with radio buttons.
Switch can be faster and easier to read, If-Then is more generic and will work in more places.
The only time switches can be faster are when your case values are constants, not dynamic or otherwise derived, and when the number of cases is significantly larger than the time to calculate a hash into a lookup table.
Case in point for Javascript, which compiles to assembly for execution on most engines, including Chrome's V8 engine, is that switch statements are 30%-60% slower to execute in the common case: http://jsperf.com/switch-if-else/20