Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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

...

The examples here fall under the exception MSC17-C-EX2 in MSC17-C. Finish every set of statements associated with a case label with a break statement.

...

Code Block
bgColor#FFCCCC
langc
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

When i = 1, the entire for loop is executed. When i = 2, two increments to j are made before the loop starts. When i = 3, one increment to j is made before the loop starts. The default case is no loop. Consequently, the function has the following behavior:

i

f(i)

1

12

2

12

3

11

Other values

0

Compliant

...

Solution

The compliant example solution separates the switch and for blocks:

Code Block
bgColor#CCCCFF
langc
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 legal 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

...

Solution (Duff's Device)

This is an alternative implementation of Duff's device, which separates the switch statement and loop:

Code Block
bgColor#CCCCFF
langc
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++;
}

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC20-C

medium

Medium

probable

Probable

medium

Medium

P8

L2

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
switch-labelFully checked
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
LANG.STRUCT.SW.MPC

Misplaced case

ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.MSC20

Fully implemented

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C2019
LDRA tool suite
Include Page
LDRA_V
LDRA_V
245 SFully implemented
PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

646, 9055

Fully supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. MSC20-CChecks for situations where switch label is not at the outermost level of switch statement body (rec. fully covered)


RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
switch-labelFully checked
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
S1036

Related Guidelines

Bibliography

[ISO/IEC 9899:2011]
Section
Subclause 6.8.6.1, "The goto Statement"
[Duff 1988]Tom Duff on Duff's Device
 

...


...

Image Modified Image Modified Image Modified