Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Clarified/simplified switch NCCE and CS.

...

Noncompliant Code Example (Switch)

This The following noncompliant code example fails to consider all possible cases. This can be the correct behavior in this case, but failure Failure to account for all the valid values of widget_ type can Color will result in logic errors if widget_type unexpectedly assumes a different value or if its valid range is expanded during code maintenance, and the programmer overlooks the need to add a case to the switch.This is particularly problematic in C because an identifier declared as an enumeration constant has type int. As a result, a programmer can accidentally assign an arbitrary integer value to an enum type, as shown in this examplea logic error. Since valid values of an enumerated type include all those of its underlying integer type, unless enumeration constants have been provided for all those values the default label is appropriate and necessary.

Code Block
bgColor#FFCCCC#ffcccc
typedef enum WidgetEnum { WE_WRed, WE_XGreen, WE_Y, WE_Z Blue } widget_typeColor;

widget_type = 45;

switch (widget_typeconst char* f(Color c) {
  switch (c) {
    case WE_XRed:
 return "Red";
  /* ... */
    break;
  case WE_Y:
    /* ... */
    break;
  case WE_Z:
    /* ... */
    break case Green: return "Green";
    case Blue: return "Blue";
  }
}

void g() {
  Color unknown = (Color)123;
  puts(f(unknown));
}

Implementation Details

...

Compliant Solution (Switch)

This The compliant solution explicitly checks for the unexpected condition by adding a default clause to the switch statement.below takes care to provide the default label to handle all valid values of type Color:

Code Block
bgColor#ccccff
typedef enum WidgetEnum { WE_WRed, WE_XGreen, WE_Y, WE_ZBlue } widget_typeColor;

widget_type = WE_X;

switch (widget_typeconst char* f(Color c) {
  case WE_W:
    /* ... */switch (c) {
    break;
  case WE_XRed:
    /* ... */
    break;
return "Red";
    case WE_YGreen:
    /* ... */
    break;
return "Green";
    case WE_ZBlue:
    /* ... */
    break;
return "Blue";
    default: return /* can't happen */
    /* handle error condition"Unknown color";   /* necessary */
    break;}
}

Adding Note that adding a default case to a switch statement, even when all possible switch labels are specified, is an allowable exception (MSC07-EX1) to recommendation MSC07-C. Detect and remove dead code, as the unreachable code is added as a precautionary measure..

An alternative compliant solution to the noncompliant code example above is to provide a return statement after the switch statement. Note, however, that this solution may not be appropriate in all situations.

Code Block
bgColor#ccccff

typedef enum { Red, Green, Blue } Color;
const char* f(Color c) {
  switch (c) {
    case Red: return "Red";
    case Green: return "Green";
    case Blue: return "Blue";
  }
  return "Unknown color";   /* necessary */
}

Historical Discussion

This practice has been a subject of debate for some time, but a clear direction has emerged.

...