A switch
statement can be mixed with a block of code by starting the block in one case label, then having another case label within the block. The block can be pictured as spanning more than one case statement.
Section Subclause 6.8.4.2, paragraph 2, of the C Standard [ISO/IEC 9899:2011] says,
If a switch statement has an associated case or default label within the scope of an identifier with a variably modified type, the entire switch statement shall be within the scope of that identifier.154
...
Code Block | ||||
---|---|---|---|---|
| ||||
int f(int i) { int j=0; switch (i) { case 1: for(j=0;j<10;j++) { //* No break,; process case 2 as well */ case 2: //* switch jumps inside the for block */ j++; //* No break,; process case 3 as well */ case 3: j++; } break; default: //* Default action */ break; } return j; } |
Implementation Details
...
Code Block | ||||
---|---|---|---|---|
| ||||
int f(int i) { int j=0; switch (i) { case 1: //* No break,; process case 2 as well */ case 2: j++; //* No break,; process case 3 as well */ case 3: j++; break; default: //* Default action */ return j; } for(j++;j<10;j++) { j+=2; } return j; } |
Noncompliant Code Example (Duff's Device)
Duff's device is a curious optimization applied to code intended to perform a serial copy. That is, it copies a series of bytes into one memory output in turn. A simple code to do this would be as follows:
Code Block |
---|
size_t count; /* Must be nonzero */ char *to; /* Output destination */ char *from; /* Points to count bytes to copy */ do { *to = *from++; /* / * Note that the "to" pointer * is NOT incremented. */ } while (--count > 0); |
...
The code is widely considered to be valid C and C++ and is supported by all compliant compilers. When describing Duff's device, the creator [Duff 1988] noted,
Many people . . . have said that the worst feature of C is that switches don't break automatically before each case label. This code forms some sort of argument in that debate, but I'm not sure whether it's for or against.
Compliant Code Example (Duff's Device)
This is an alternative implementation of Duff's device, which separates the switch
statement and loop:
Code Block | ||||
---|---|---|---|---|
| ||||
int n = (count + 7) / 8; switch (count % 8) { case 0: *to = *from++; /* fallFall through */ case 7: *to = *from++; /* fallFall through */ case 6: *to = *from++; /* fallFall through */ case 5: *to = *from++; /* fallFall through */ case 4: *to = *from++; /* fallFall through */ case 3: *to = *from++; /* fallFall through */ case 2: *to = *from++; /* fallFall through */ case 1: *to = *from++; /* fallFall through */ } while (--n > 0) { *to = *from++; *to = *from++; *to = *from++; *to = *from++; *to = *from++; *to = *from++; *to = *from++; *to = *from++; } |
...
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC20-C | mediumMedium | probableProbable | mediumMedium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
| CC2.MSC20 | Fully implemented |
...
CERT C++ Secure Coding Standard | MSC20-CPP. Do not use a switch statement to transfer control into a complex block |
ISO/IEC TR 24731-1:2007 | |
MISRA C:2012 | Rule 16.2 (required) |
Bibliography
[ISO/IEC 9899:2011] | Section Subclause 6.8.6.1, "The goto Statement" |
[Duff 1988] | Tom Duff on Duff's Device |
...