Why no compile error?

The following sketch doesn’t generate a compile error and is running but…

void setup() {
  Serial.begin(38400);
  delay(3);
  Serial.println();
  Serial.println("----------------------------");

  uint8_t sx = 2;
  Serial.print("sx set to 2 ");
  switch (sx) {
    case1:
      Serial.print("sx=1");
      break;
    case2:
      Serial.print("sx=2");
      break;
    case3:
      Serial.print("sx=3");
      break;
  }
  Serial.println(" stop");
}

void loop() {
  // put your main code here, to run repeatedly:

}

The sketch contains errors: within switch statement spaces are missing after case.

The output is:

----------------------------
sx set to 2  stop

i.e. the switch statement doesn’t work.

Why?

Hi, presumably case1, case2 etc are considered labels for goto.

1 Like

Try case 1; (with a space).
For more syntax: https://docs.arduino.cc/language-reference

1 Like

i get following with File->Preferences->compiler warnings set to "more"











C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In function 'void setup()':
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:10:5: warning: label 'case1' defined but not used [-Wunused-label]
     case1:
     ^~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:13:5: warning: label 'case2' defined but not used [-Wunused-label]
     case2:
     ^~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:16:5: warning: label 'case3' defined but not used [-Wunused-label]
     case3:
     ^~~~~
Sketch uses 4568 bytes (14%) of program storage space. Maximum is 32256 bytes.
Global variables use 236 bytes (11%) of dynamic memory, leaving 1812 bytes for local variables. Maximum is 2048 bytes.

As the warnings produced when compiling the code say

C:\Users\micro\AppData\Local\Temp\.arduinoIDE-unsaved2025918-17880-isaf1l.crxap\sketch_oct18a\sketch_oct18a.ino: In function 'void setup()':
C:\Users\micro\AppData\Local\Temp\.arduinoIDE-unsaved2025918-17880-isaf1l.crxap\sketch_oct18a\sketch_oct18a.ino:12:1: warning: label 'case1' defined but not used [-Wunused-label]
C:\Users\micro\AppData\Local\Temp\.arduinoIDE-unsaved2025918-17880-isaf1l.crxap\sketch_oct18a\sketch_oct18a.ino:15:1: warning: label 'case2' defined but not used [-Wunused-label]
C:\Users\micro\AppData\Local\Temp\.arduinoIDE-unsaved2025918-17880-isaf1l.crxap\sketch_oct18a\sketch_oct18a.ino:18:1: warning: label 'case3' defined but not used [-Wunused-label]

Lets look at the switch statement:

It contains some strange labels, which are not used (case1, case2, case3), but it is allowed and legal, so it issues just warnings.

It contains some code, and it is also allowed.

The value of sx was not met in any case inside (because there are no cases inside, but it is also allowed) and there is no default, so nothing is executed inside, excactly as C++ was specified.

So the switch compiles and works exactly as you wrote it. (And in totally different way, than you want it. It is what computers do all the time :slight_smile: )

yep, definitely

I am compelled to add a little noise here to say…

… that is the weirdest totally explicable mistake I have ever seen.

I wish I had not read the solution; it would make a pretty good question for a test of C/C++ knowledge.

Of course many of us never use labels because we never use goto. So failing to recognize case1 for what it is in this context might be forgivable.

Once again, a good reason to enable compiler warnings and heed the red ink.

a7

I’ve always like using -Werror
Yeah it can be a pain to clean up some code, but it can also find a some hidden issues.

Unfortunately last I checked, the Arduino core code was not clean enough to use it.

Nor is much of the library code.

1 Like

A switch statement can contain code that isn’t part of a case?
What does that do?

In C++, a switch statement syntax is basically

switch (condition) statement

so based on that definition, the statement (typically a compound statement) can contain code outside any case or default label and this is legit.

But the spec states as well

When the condition of a switch statement yields a (possibly converted) value:

  • If one of the associated case label constants has the same value, control is passed to the statement labeled by the matched case label.
  • Otherwise, if there is an associated default label, control is passed to the statement labeled by the default label.
  • Otherwise, none of the statements in the switch statement will be executed.

➜ Any code in the switch block that is not part of a case or default label will end up being ignored (unreachable when a matching case exists unless control happens to fall through from a previous case).

Any code that has no case label can't be "fall[en] through" to... it's part of the "previous case".

So except for traditionally unreachable code, only the first statements in the { } of the switch, if keft without the case label, woukd be unreachable.

a7

Just out of idle curiosity, I built an equivalent of the OP's original switch statement using the nearest I could get to a computed goto in C++ :

// based on: https://stackoverflow.com/questions/45380073/can-you-make-a-computed-goto-in-c
// compiled for a Mega2560

void setup() {
  Serial.begin(115200);
  delay(3);
  Serial.println();
  Serial.println("----------------------------");

  uint8_t sx = 2;
  Serial.print("sx set to 2 ");

  static const void* array[] = { &&case1, &&case2, &&case3 };
  goto* array[sx - 1];

case1:
  Serial.print("sx=1");
  goto end1;
case2:
  Serial.print("sx=2");
  goto end1;
case3:
  Serial.print("sx=3");
  goto end1;

end1:
  Serial.println(" stop");

}

void loop() {
  // put your main code here, to run repeatedly:
}

That is what OP wanted, but not what he wrote :slight_smile: You have put unconditional goto end1; before the goto* to reflect, that he did not used the jump labels anywhere :slight_smile:

Fair - yes

Still no spaces (see post #3).

Indeed. But it works and gives the correct answer.

Incidentally, the OP knew the error he had made. He was surprised only that he did not get an appropriate message from the compiler.

Then the solution would be to switch 'verbose' on, not using arrays and pointers to circumvent a problem that could have been solved with a few spaces.