Switch...case работает не так как ожидалось. Объявление переменных

Здравствуйте!
Объясните, пожалуйста, в чем причина? Почему без скобок не обрабатываются все case от 2 и ниже?

byte tt=1;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(tt);

  switch (tt)
  {
    case 1:
      Serial.println("#PUBLISH");
      //{//###БЕЗ ЭТИХ СКОБОК НЕ ВЫВОДИТСЯ Serial.println() ВО ВСЁМ switch...case ниже !!!!!?????
      byte lepl=1;
      //}//###БЕЗ ЭТИХ СКОБОК НЕ ВЫВОДИТСЯ Serial.println() ВО ВСЁМ switch...case ниже !!!!!?????
      break;
    case 2:
      Serial.println("#PUBACK");
      break;
    case 3:
      Serial.println("#SUBACK");
      break;
    case 4:
      Serial.println("#PINGRESP");
      break;
    default:
      Serial.println("#unknown packet");
  }
  if (++tt == 6)
  {
    tt=1;
    Serial.println();
    delay(1000);
  }
}

Снимок

Без этих скобок код некорректный и вообще не должен компилироваться

Ну как бы результат на скриншоте. Arduino 1.8.19.

Видимо это как раз проявление “неопределённого поведения”, который заявляется для случаев нарушения стандарта, когда промокашкой начинают мешать компот, а напильником ковырять в ухе.

Отличное пояснение!

Всем спасибо нашел, разобрался https://metanit.com/cpp/tutorial/2.17.php

Переменные в блоках case

Определение переменных в блоках case, возможно, встречается нечасто. Однако может вызвать затруднения. Так, если переменная определяется в блоке case, то все инструкции блока помещаются в фигурные скобки (для блока default это не требуется):

Строка 15. Не нужно инициализировать переменную в момент ее объявления. Если так уж нужно объявить переменную в case, то нужно делать так

byte lepl;
lepl=1;

Собственно, компилятор об этом предупреждает, но кто ж его предупреждения смотрит? ))

1 лайк

Бред. Код всё равно некорректный и никакой разницы в плане результирующего машкода нет.

Да, действительно. Этот вариант тоже работает. Такие неожиданности с инициализацией в момент объявления переменных только с case бывают?

Никаких неожиданностей - вам же уже намекнули на нарушение стандарта :wink:
Просто запомните, что в case инициализировать переменные нельзя

1 лайк

При goto на метку и объявлении посередине функции компилятор тоже ругается на кросс-инициализацию. Потому что переменная должна быть достижима везде, а свичи и goto потенциально это рушат, потому что туда-сюда заставляют прыгать и не факт, что твой case 1 с объявлением вообще исполнится, но заюзать ниже ты переменную можешь.

1 лайк

Можно, но ограничивая область видимости скобками.

2 лайка

Про скобки он уже сам раскопал ))

Все же интересно после компилятора посмотреть. Предполагаю, что он выкинул все case, кроме # 1, ограничив таким образом область видимости объявленной переменной скобками свича.

Андрей, поясните, смысл то в чем, зачем в кейсе переменную инициализировать? Эта переменная абсолютно бесполезна.
По правилам языка вы ее все равно нигде ниже использовать не можете