Versions Compared

Key

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

...

This noncompliant code example fails to test for conditions where a is neither b nor c. This may be the correct behavior in this case, but failure to account for all the values of a can result in logic errors if a unexpectedly assumes a different value.

Code Block
bgColor#FFCCCC
langc
if (a == b) {
  /* ... */
}
else if (a == c) {
  /* ... */
}

...

This compliant solution explicitly checks for the unexpected condition and handles it appropriately.

Code Block
bgColor#ccccff
langc
if (a == b) {
  /* ... */
}
else if (a == c) {
  /* ... */
}
else {
  /* handle error condition */
}

...

The following noncompliant code example fails to consider all possible cases. Failure to account for all valid values of type Color will result in a 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
langc
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";
  }
}

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

...

The compliant solution below takes care to provide the default label to handle all valid values of type Color:

Code Block
bgColor#ccccff
langc
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";
    default: return "Unknown color";   /* necessary */
  }
}

...

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
langc
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 */
}

...

The flaw in the code occurs when days has the value 366 because the loop never terminates. This bug manifested itself on the 366th day of 2008, which was the first leap year in which this code was active.

Code Block
bgColor#FFCCCC
langc
#define ORIGINYEAR 1980
UINT32 days = /* number of days since January 1, 1980 */
int year = ORIGINYEAR;
/* ... */

while (days > 365) {
  if (IsLeapYear(year)) {
    if (days > 366) {
      days -= 366;
      year += 1;
    }
  }
  else {
    days -= 365;
    year += 1;
  }
}

...

This proposed rewrite is provided by http://www.aeroxp.org/2009/01/lesson-on-infinite-loops. The loop is guaranteed to exit, as days decreases for each iteration of the loop, unless the while condition fails, and the loop terminates.

Code Block
bgColor#ccccff
langc
#define ORIGINYEAR 1980
UINT32 days = /* input parameter */
int year = ORIGINYEAR;
/* ... */

int daysThisYear = (IsLeapYear(year) ? 366 : 365);
while (days > daysThisYear) {
  days -= daysThisYear;
  year += 1;
  daysThisYear = (IsLeapYear(year) ? 366 : 365);
}

...