Today when I am listening to a podcast about MISRA C, I came to know about some interesting fact about switch statement in C. The explanation with example about it can be found here.
Imagine a calculation depending on certain numbers being prime or not. If the routine gets a prime parameter it executes one routine, if the parameter is not prime, another. Like this:
if (is_prime(a))
··process_prime(a);
else
··process_nonprime(a);
The if-statement is just that, a statement, a composite statement.
A switch-statement is composed of a switch keyword, the value on which to operate, and a, possibly composite, statement. It could be our if-statement, if we so choose. However, without any case/default-labels, the switch-statement would just jump over the statement so specified, effectively doing nothing. To remedy that, we put the default-label before the if-statement:
switch (a)
··default:
····if (is_prime(a))
······process_prime(a);
····else
······process_nonprime(a);
This code already looks strange, but it is functionally equivalent to the if-statement by itself.
If we now imagine the function is_prime(a) to be very expensive, it would make sense to take a shortcut around that function wherever possible. And if 99% of the values the variable a can have lie between 2 and 10 inclusive, it definitely would make sense to circumvent the is_prime() function, since we know the primeness of those values without calculation:
switch (a)
··default:
····if (is_prime(a))
··case 2: case 3: case 5: case 7:
······process_prime(a);
····else
··case 4: case 6: case 8: case 9: case 10:
······process_nonprime(a);
To understand why this is correct C, we need to realize that case-labels belonging to a switch-statement can be positioned anywhere within the boundaries of the composite statement belonging to the switch. In our case, this means until the semicolon after the process_nonprime(a) statement.
It works as follows:
If a is 3 upon execution of the switch, the label case 3: is where execution continues after determining the value of a to be three, jumping into the middle of the if-statement and calling the function process_prime with a parameter 3. After execution of that function, the if-statement is terminated, terminating the enclosing switch-statement at the same time.
If a is 8 upon execution of the switch, the label case 8: is where execution continues after determining the value of a to be eight, jumping into the middle of the if-statement and calling the function process_nonprime with a parameter 8. After execution of that function, the if-statement is terminated, terminating the enclosing switch-statement at the same time.
If a is 29 upon execution of the switch, the label default: is where execution continues after determining that no known value is to be processed, executing the if-statement from its beginning. Depending on the value of a (29 in this case) the if-condition determines which of the two alternative functions to call, just like a normal if-statement.
No comments:
Post a Comment