Why can't we use variables inside a case in switch construct? - c

If I have an integer variable like int a=4 then in the switch case If i write
int b = something;
...
switch(a)
{
case 4+b: printf("hii");
}
then why is this statement a compile-time error that variables cannot be used inside a case statement why does the compiler not subtitutes the values in place of the variables.
So basically what problem it creates for which the language developers did not include it as a proper syntax.

The initial idea of the switch control-flow statement was that it should determine the appropriate case very quickly, while potentially having a lot of cases.
A traditional implementation would use a jump table, making it an O(1) operation. The jump table is essentially an array of pointers, where each pointer contains the address of the first instruction for each case. Jumping to the appropriate case is as simple as indexing that array with the switch value and then doing a jump instruction to that address.
If the cases were allowed to contain variables, the compiler would have to emit code that first evaluates these expressions and then compares the switch value against more than one other value. If that was the case, a switch statement would be just a syntactically-sugarized version of a chain of if and else if.
switch statements are usually at the heart of any algorithm which implements a finite-state machine (like parsers), so that was a good reason to include it into the language. Most modern compilers would probably generate identical machine code for a chain of if and else if which are only testing a variable against a constant, but that wasn't the case in the early 1970s when C was conceived. Moreover, switch gives you the ability to fall-through which isn't possible in the latter arrangement.

case 2+a: doSomething();
break:
case 4-a: doSomethingElse();
break;
What do you do when a==1?
There are several possible answers, including
Run all applicable cases, in order
Run all applicable cases, in arbitrary order
Run the first applicable case
Run any one applicable case
The behaviour is undefined
Raise a well-defined error
The problem is, none of the resolutions is preferred over the others. Moreover, all run contrary to the original simple rationale of the switch statement, which is providind a high(ish) level abstraction of a fast, precomputed indexed jump table.

Because it is usually superfluous, and on a compiler level you want a jump to a fixed address. Just put the dependency of the variable in the switch expression
switch(a-b)
{
case 4: printf("hii");
}

Related

How Switch Statement Works

How does a switch statement immediately drop to the correct location in memory? With nested if-statements, it has to perform comparisons with each one, but with a switch statement it goes directly to the correct case. How is this implemented?
There are many different ways to compile a switch statement into machine code. Here are a few:
The compiler can produce a series of tests, which is not so inefficient as only about log2(N) tests are enough to dispatch a value among N possible cases.
The compiler can produce a table of values and jump addresses, which in turn will be used by generic lookup code (linear or dichotomic, similar to bsearch()) and finally jump to the corresponding location.
If the case values are dense enough, the compiler can generate a table of jump addresses and code that checks if the switch value is within a range encompassing all case values and jump directly to the corresponding address. This is probably the implementation closest to your description: but with a switch statement it goes directly to the correct case.
Depending on the specific abilities of the target CPU, compiler settings, and the number and distribution of case values, the compiler might use one of the above approaches or another, or a combination of them, or even some other methods.
Compiler designers spend a great deal of effort trying to improve heuristics for these choices. Look at the assembly output or use an online tool such as Godbolt's Compiler Explorer to see various code generation possibilities.

efficient switch statement when using enums

I have an enum and a switch statement using some of the enum entries but not all and they are currently out of order too, i.e. I have the following:
enum prot_tun_stat_e {
STAT_A = 0,
STAT_B,
STAT_C,
STAT_D,
STAT_E,
STAT_F, //5
STAT_G,
STAT_H,
STAT_I,
STAT_Y,
STAT_K, //10
STAT_COUNT //must be last
} __attribute__((packed));
and then I have a switch using the following entries:
switch(var) {
case C:
break;
case D:
break
case F:
break
case G:
break
default
}
and I was wondering if I better rearranged the items in the enum to be C=1,D=2,F=3&G=4 ? Would that be more efficient?
Thanks,
Ron
Platform: PowerPC, compiler diab
If the compiler can determine that the parameter to the switch statement is limited to a small number then it can create a jump table. This table will take up less room if the values are contiguous but the difference between 4 entries or the 10 required is unlikely to matter. (And note that 0-3 is a better range than 1-4 - although the compiler can deal with this by jumping to offset n - 1).
You can check the output of the compiler to see if a jump table is being created (assuming you can read assembly!). And of course the answer to all performance questions: profile it!
I can't talk about the diab compiler, because I'm not familiar with it, but an optimizing compiler will most likely create a jump table for a switch statement over an enum. So the order wouldn't matter. Having said that, you shouldn't worry about such trivial things. Correct me if I misunderstood your question.

When do label declarations and label values make sense?

The GNU C Extensions provide a specification of label declarations, so that labels can be assigned to variables which can be used by gotos. While I acknowledge that goto makes sense in certain situations (e.g. as a substitute for exception handling in higher languages), I do not understand how this goto language extension could be justified. Can you provide a concrete example, where label values provide benefits?
The one time I used it to good effect was for threaded dispatch. Imagine an interpreter's inner loop:
while (1) {
switch ( *instruction_pointer ) {
case INSTR_A:
...
break;
case INSTR_B:
...
break;
...
}
++instruction_pointer;
}
The biggest performance problem with the looping construct itself is that there's one branch (ideally) in that swtich statement which is handling all instructions. That branch can never be properly predicted. With threaded dispatch you add explicit code to every case to go to the next:
void *instructions[] = { &&instr_a, &&instr_b, ... };
...
goto *instructions[*instruction_pointer];
instr_a:
...
goto *instructions[*++instruction_pointer];
instr_b:
...
goto *instructions[*++instruction_pointer];
Each instruction is able to jump directly to the start of the next instruction. Common sequences of instructions are faster due to CPU branch prediction. And it guarantees a jump table implementation, where the switch might not work out that way if the instruction space is slightly sparse.

Transform any program into a semantically equivalent one

I recently found this theorem here, (at the bottom):
Any program can be transformed into a semantically equivalent program of one procedure containing one switch statement inside a while loop.
The Article went on to say :
A corollary to this theorem is that any program can be rewritten into a program consisting of a single recursive function containing only conditional statements
My questions are, are both these theorems applicable today ? Does similarly transforming a program reap any benefits ? I mean to say, is such a code optimized ? (Although recursion calls are slower, I know)
I read, from here, that switch-cases are almost always faster when optimized by the compiler. Does that make a difference. ?
PS: I'm trying to get some idea about compiler optimizations from here
And I've added the c tag as that's the only language I've seen optimized.
Its true. A Turing machine is essentially a switch statement on symbols that repeats forever, so its based pretty directly on Turing-machines-compute everything. A switch statement is just a bunch of conditionals, so you can clearly write such a program as a loop with just conditionals. Once you have that, making the loop from recursion is pretty easy although you may have to pass a lot of state variables as parameters if your language doesn't have true lexical scoping.
There's little reason to do any of this in practice. Such programs generally operate more slowly than the originals, and may take more space. So why would you possibly slow your program down, and/or make its load image bigger?
The only place this makes sense is if you intend to obfuscate the code. This kind of technique is often used as "control flow obfuscation".
This is basically what happens when a compiler translates a program into machine code. The machine code runs on a processor, which executes instructions one-by-one in a loop. The complex structure of the program has become part of the data in memory.
Recursive loops through a switch statement can be used to create a rudimentary virtual machine. If your virtual machine is Turing complete then, in theory, any program could be rewritten to work on this machine.
int opcode[] {
PUSH,
ADD
....
};
while (true) {
switch (*opcode++) {
case PUSH:
*stack++ = <var>;
break;
case ADD:
stack[-1] += stack[0];
--stack;
break;
....
}
}
Of course writing a compiler for this virtual machine would be another matter.
:-)

Nested if or switch case statement

From the point of view of optimizing the code run time, is there a thumb rule for where to use "nested if" statement and when to use "switch case" statements ?
I doubt you will ever find a real-life application where the difference between a nested if and a switch case is even worth measuring. Disk access, web access, etc. take many many orders of magnitude more time.
Choose what is easiest to read and debug.
Also see What is the difference between IF-ELSE and SWITCH? (possible duplicate) as well as Advantage of switch over if-else statement. Interestingly, a proponent of switch writes
In the worst case the compiler will
generate the same code as a if-else
chain, so you don't lose anything. If
in doubt put the most common cases
first into the switch statement.
In the best case the optimizer may
find a better way to generate the
code. Common things a compiler does is
to build a binary decission tree
(saves compares and jumps in the
average case) or simply build a
jump-table (works without compares at
all).
If you have more than 2-3 comparisons
then "switch"
else "if"
try to apply some patterns before you go to switch like strategy...
I don't believe it will make any difference for a decision structure that could be implemented using either method. It's highly likely that your compiler would produce the same instructions in the executable.

Resources