#defined names of switch (error: jump to case label )

I have defines so my ints used for switch cases mean something!

//display mgr
#define READ 1
#define WRITE 2
#define FLASH 3
#define UP 4
#define DOWN 5
#define APPEND 6

and the switch statement…

String displayMgr(int dMode = READ, String strLine = "") {
  static String displayList[32];
  static String displayCur[2];
  static int showLine;
  static int li;
  switch (dMode) {
    case READ:
      String out = ">";
      for (int i = 0; i <= 32; i++) {
        out = String(out) + String("\n") + String(i) + String(": ") + display[i];
      }
      return out;
      break;
    case APPEND:
      displayList[li] = displayList[li] + strLine;
      showLine = li;
      displayCur[0] = displayList[showLine] ;
      displayCur[1] = displayList[showLine + 1];
    case WRITE:
      //find first empty, or cycle out
      for (int i = 32; i >= 0; i--) {
        display[i] = display[i + 1];
        if (display[i] = "") {
          li = i;
          break;
        }
      }
      display[li] = strLine;
      showLine = li - 1;
      break;
    case UP:
      //move display window up
      showLine--;
      displayCur[0] = displayList[showLine];
      displayCur[1] = displayList[showLine + 1];
      break;
    case DOWN:
      //move display window down
      showLine++;
      displayCur[0] = displayList[showLine];
      displayCur[1] = displayList[showLine + 1];
      break;
    case FLASH:
      static int lcdBLState = 0;
      lcdBLState = !lcdBLState;
      if (lcdBLState == 0) {
        lcd.noBacklight();
        return "1";
      }
      else {
        lcd.backlight();
        lcdBLState = 1;
      }
      break;
  }
  lcd.backLight();
  lcd.setCursor(0, 0);
  lcd.print(displayCur[0]);
  lcd.setCursor(0, 1);
  lcd.print(displayCur[1]);
}

Heres the ERRORS:

washMgr:48:15: error: jump to case label [-fpermissive]

 #define WRITE 2...

This is a kind of weird error in that the more meaningful part comes a few lines down in the output “crosses initialization of”…

You have initialized the out variable inside the READ case, which caused the error. The way to fix this is to wrap the case code in braces, which makes the out variable local to that scope:

case READ:
  {
    String out = ">";
    for (int i = 0; i <= 32; i++) {
      out = String(out) + String("\n") + String(i) + String(": ") + display[i];
    }
    return out;
  }
  break;

Yeah, that was very misleading... I thought I coudln't use a defined label inside a switch statement. I declared vars up front and it got thru..

The FULL warning message is:

/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino:3:15: warning: jump to case label [-fpermissive]
 #define WRITE 2
               ^
/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino:27:10: note: in expansion of macro 'WRITE'
     case WRITE:
          ^~~~~
/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino:16:14: note:   crosses initialization of 'String out'
       String out = ">";
              ^~~

It's saying that the jump to "case 2:" on line 27 (the '2' being the expansion of the macro 'WRITE' declared on line 10) jumps past the initialization of the local variable 'out' declared on line 14. If that jump were allowed then the local variable would be 'in scope' (visible) but not initialized.

mattlogue:
I have defines so my ints used for switch cases mean something!

Using an enum would be better.

Using an enum would be better

Whilst I would use an enum to define the states, which means that I don't even have to know what value has been assigned to them, I don't see that an enum is "better"

UKHeliBob:
Whilst I would use an enum to define the states, which means that I don't even have to know what value has been assigned to them, I don't see that an enum is "better"

One advantage is that the compiler can warn you if you don't have a case for every member of the enum. That warning makes the enum choice 'better' in my book.

One advantage is that the compiler can warn you if you don’t have a case for every member of the enum.

That sounds good, but does this behavior need to be enabled somehow ? For instance, this compiles with no warnings

enum cases
{
  ONE,
  TWO,
  THREE
};
byte currentCase = ONE;

void setup()
{
  Serial.begin(115200);
  while (!Serial);
}

void loop()
{
  switch (currentCase)
  {
    case ONE:
      break;
  }
}

Change the type of 'currentCase ' to cases and you'll get the warnings.

I think it’s “better” any time you can get the compiler to do something for you rather than using a preprocessor macro.

Also, enum allows you to specify the underlying data type. So, for most Arduino state machine implementations, a uint8_t is sufficient.

Just comment out a few characters...

enum cases
{
  ONE,
  TWO,
  THREE
} /* ;
byte */ currentCase = ONE;
/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino: In function 'void loop()':
/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino:17:10: warning: enumeration value 'TWO' not handled in switch [-Wswitch]
   switch (currentCase)
          ^
/Users/john/Documents/Arduino/sketch_dec25a/sketch_dec25a.ino:17:10: warning: enumeration value 'THREE' not handled in switch [-Wswitch]
Sketch uses 1438 bytes (4%) of program storage space. Maximum is 32256 bytes.
Global variables use 184 bytes (8%) of dynamic memory, leaving 1864 bytes for local variables. Maximum is 2048 bytes.

Thanks - it had never occurred to me to use the name of the enum in that way, forgetting entirely that the enum was in fact defining a type. I will certainly try to remember to use enums in that way in future.

Is it my imagination (bad memory ?) or wasn't the use of typedef mandatory at some time in the past ?

In good-old 'C' you had to use typedef to give a name to a struct to avoid having to use 'struct structName' all the time.

I'm pretty sure this was not the case with enums.

gfvalvo:
In good-old 'C' you had to use typedef to give a name to a struct to avoid having to use 'struct structName' all the time.

I'm pretty sure this was not the case with enums.

No, it is the same for enums. In C, you use a typedef to avoid having to use 'enum enumName'.

This is not the case in C++, where you can just use the enum name directly.

Pieter