Switches, default, and enums

6.15 Switch Statements

Moderators: misra-c, david ward

Locked
ChrisNelson
Posts: 1
Joined: Thu May 24, 2007 12:49 pm
Location: Clifton Park, NY, USA

Switches, default, and enums

Post by ChrisNelson » Thu May 24, 2007 1:38 pm

Rule 15.3 requires every switch to end with a default clause. While this is usually a good idea, it undermines the technique of using enums for switch control and having the compiler catch unused or unhandled values. For example:

Code: Select all

   typedef enum {
      red,
      green,
      blue
   } color_t;

   void f(color_t color) {
      switch (color) {
      case red:
         /* do something */
         break;
      case green:
         /* do something */
         break;
   }

Many compilers and certainly most lints will generate a warning when compiling the function f noting that not all enum values are handled. When the typedef and the switch are in different files, this can be quite helpful. When the enum is handled by switches in multiple source files, this structure allows the compiler to catch unmodified switches when a new enum value is added. If there was a default case in this switch, the compiler would not complain.

With that in mind, I suggest that rule 15.3 be revised by adding, \"except where the switch expression is an enum\" to the end. I might also add a advisory rule encouraging switch expressions to be enums.

Any thoughts?

sparker
Posts: 13
Joined: Thu Apr 28, 2005 2:05 pm
Location: Cambrige, UK

Re: Switches, default, and enums

Post by sparker » Fri May 25, 2007 9:14 am

ChrisNelson wrote:Rule 15.3 requires every switch to end with a default clause. [...] For example:

Code: Select all

   typedef enum {
      red,
      green,
      blue
   } color_t;

   void f(color_t color) {
      switch (color) {
      case red:
         /* do something */
         break;
      case green:
         /* do something */
         break;
   }

Many compilers and certainly most lints will generate a warning when compiling the function f noting that not all enum values are handled. [...]
With that in mind, I suggest that rule 15.3 be revised by adding, "except where the switch expression is an enum" to the end. I might also add a advisory rule encouraging switch expressions to be enums.

Any thoughts?
While I have some sympathy with this position, we have to realise that enums are just ints beneath, and there's nothing much to stop you writing

Code: Select all

f((color_t) -1);
so we have to balance the static checking offered by the lint against the dynamic checking available through a suitable default case.

One possibility might be to hide the default case from the lint; although this would bring up another set of issues needing justification.

As usual, where there is some debate in the issue, it is probably best if you raise a deviation to the rule containing your proviso ("except where the switch expression is an enum") with appropriate justification.

stephen

lv
Posts: 9
Joined: Mon Oct 31, 2005 12:47 pm

Re: Switches, default, and enums

Post by lv » Wed Jun 06, 2007 12:30 pm

ChrisNelson wrote:Many compilers and certainly most lints...
Then it cannot be a MISRA rules because it is not "all compiler", and this is not applicable for all compiler because this behavior (generat a warning in this case) is unspecified by the ISO 9899.

That could only be a project/company deviation.

misra-c
Posts: 569
Joined: Thu Jan 05, 2006 1:11 pm

Post by misra-c » Tue Dec 11, 2007 11:05 am

sparker's reply is consistant with the view of the working group.
---
Posted by and on behalf of
the MISRA C Working Group

Peter Obermayer
Posts: 1
Joined: Wed Jan 09, 2008 3:21 pm
Location: Wetzlar

Re: Switches, default, and enums

Post by Peter Obermayer » Wed Jan 09, 2008 4:30 pm

Do I understand correctly that even if the cases of a switch statement exhaust all elements of an enum the default statement is not \"unreachable\" in the sense of MISRA-2004:14.1 / MISRA 98:52 due to the argument given by sparker?

George Brown
Posts: 10
Joined: Fri Jul 13, 2007 1:13 pm

Post by George Brown » Wed Jan 09, 2008 5:12 pm

When writing code for safety-critical systems, I have always considered treating all RAM locations to be \"volatile\" in nature. If I have code which can set a 16 bit unsigned integer (represeting an enum) explicitly to the values of 0, 1, 2, and 3, I also always handle the cases of it being any other value the storage may select, i.e. 4 to 65535.

Given

Code: Select all

typedef enum { 
   red, 
   green, 
   blue 
} color_t; 

   ...
   color_t color;
   ...
   color = red;
   ...
   { 
      switch (color) { 
      case red: 
         /* do something */ 
         break; 
      case green: 
         /* do something */ 
         break;
      case blue:
         /* do something */ 
   }
Treat color to be volatile, and assume that a failure mechanisum WILL exist to randomly set it.
Given this, the need for the default clause is not in question. (imho)

George
Embeded Software developer since 85.

Lundin
Posts: 70
Joined: Mon Dec 10, 2007 1:57 pm

Post by Lundin » Mon Jan 14, 2008 11:42 am

I agree completely with George, an important purpose of the rule is defensive programming against \"RAM noise\", ie in a safety-critical system the RAM can't be trusted to keep its values during long periods of time. Also, if there is an undetected runtime bug altering a memory location unexpectedly, the bug can be detected, and damage caused by it avoided, if using this method.

The same argument can be used for justifying rule 14.10 saying that you must end an \"if...else if\" with \"else\".

Locked

Return to “6.15 Switch Statements”