оператор goto

Тема в разделе "Arduino & Shields", создана пользователем issaom, 19 окт 2017.

  1. issaom

    issaom Гуру

    Знатоки кода подскажите пожалуйста почему компилируется

    Код (C++):
    void loop() {

    lab:

    if (digitalRead(13)){goto lab;}

    }
    а вот так не компилируется

    Код (C++):
    void loop() {

    if (digitalRead(13)){goto lab;}

    lab:

    }

    и можно ли размещать метки перехода после того как них ссылаешься !?
     
  2. DIYMan

    DIYMan Guest

    Компилироваться должно в обеих случаях. По вопросу - да, можно.

    З.Ы. Попробуйте в некомпилируемом случае поставить точку с запятой после метки, т.е.:

    Код (C++):
    void loop() {

    if (digitalRead(13)){goto lab;}

    lab: ;

    }
     
    issaom нравится это.
  3. issaom

    issaom Гуру

    за З.Ы. отдельное спасибо - вот и читай документацию в интернете - всю башку изломал )))
    http://arduino.ua/ru/prog/Goto
     
  4. DIYMan

    DIYMan Guest

    А там просто неочевидно, что после метки должны быть операторы какие-либо, поэтому и такое поведение. В вашем некомпилируемом случае - после метки пустота, возможно, это баг парсера при построении AST, поэтому и не компилится, точка с запятой решает эту проблему, как добавление в дерево разбора ветки с пустым оператором. Как-то так.
     
    issaom нравится это.
  5. issaom

    issaom Гуру

    Спасибо!

    Код (C++):
    void loop() {

    if (digitalRead(13)){goto lab;}

    lab:
    digitalWrite(13,1);
    }
    Если так то все ОК! У меня goto в теле процедуры стоит и он должен выносить из цикла в конец процедуры при определенном условии - поэтому больше там операторов нету :)
     
  6. DIYMan

    DIYMan Guest

    Ясно, что моё мнение никому не интересно, но я уже и забыл, когда возникала необходимость использовать goto. И в вашем случае, уверен, можно без него обойтись ;)
     
    Tomasina нравится это.
  7. issaom

    issaom Гуру

    Про дурной тон и "спагетти" я в курсе )))
    Но иногда правила нарушаю если от этого улучшается читаемость кода - для меня это хобби и потому может возникнуть проблема если придется что-то поправить через месяц-два
    Если интересна вот вся процедура

    Код (C++):
    void USART_Receive()
    {
      start_Rx:
      sRX = millis();                                //запоминаем текущее время
      while ( !(UCSR0A & (1 << RXC0)) )              // Ожидание поступления данных
      {
        dRX = millis() - sRX;                        //сколько ждем байт ?
        if (dRX > pRX) {goto pipec_Rx;}              // связь пропала
      }
      Bincoming[CountArr] = UDR0;                    // Получить и возвратить данные из буфера
      CountArr++;                                    // Увеличиваем счетчик входящих байт
      if (CountArr < 10) {goto start_Rx;}            // Не все байты пришли
      digitalWrite(14, HIGH);                        // Получены все байты - зажигаем светодиод связи
      pipec_Rx:;                                     // Вываливаемся сюда если связи нет
    }
    функция ждет поступления через UART пакета из 10 байт и если связь пропадает отваливается по TimeOut
     
  8. ORLENOK

    ORLENOK Гик

    Как минимум 1 goto можно убрать спокойно. Даже строк меньше будет:
    Да собственно и второй можно.
    Не нужно использоваться goto... Просто не нужно. Да удобно, но нет, не нужно.
    Кому то хобби начинает доход приносить, но для этого точно нужно делать качественно.
    Код (C++):
    void USART_Receive()
    {
      for( int i =0;i<10;i++)
    {
        sRX = millis();                                //запоминаем текущее время
        while ( !(UCSR0A & (1 << RXC0)) )              // Ожидание поступления данных
        {
          dRX = millis() - sRX;                        //сколько ждем байт ?
          if (dRX > pRX) {return;}              // Вываливаемся сюда если связи нет
        }
        Bincoming[i] = UDR0;                    // Получить и возвратить данные из буфера
    }
    digitalWrite(14, HIGH);                        // Получены все байты - зажигаем светодиод связи
    }
     
    issaom и Tomasina нравится это.
  9. issaom

    issaom Гуру

    Да я не спорю - тут если поднапрячься можно еще 2/3 операторов выкинуть - проблема в том что я еще не знаю как это будет работать целиком - может я еще сюда процедуру обработки потери связи запихну (а может нет) - мне важен результат, а он будет хоть с гото хоть без него мне как любителю пофиг (особенно учитывая тормознутость самого радиоканала) - пока это отладочный код и там очень много довольно криво написанных за то интуитивно понятных и простых секций. Если писать "по православному" нужно вообще сделать чтобы функция возвращала 0 если ничего не пришло и 1 если все ОК, а у меня на 14м пине светодиод висит - криво - за то сразу видно ок или не ок ))) и Boolean не нужен
     
  10. ostrov

    ostrov Гуру

    С гото можно лихо влететь, если пихать его куда ни попадя. Например из тела цикла куда то еще. Или из тела функции. Есть вот такой кашерный вариант, как пример.
     
  11. issaom

    issaom Гуру

    Ну Break то тут мне не совсем подходит потому-что вываливаться то мне нужно именно из всей процедуры (собственно говоря из-за этого она была и сделана) следующая попытка запроса данных поступит только через 0.5 секунды и должна она начинаться с нуля - ORLENOK предложил самый оптимальный вариант :) (в ней 2 проверки собственно что вообще что-то приходит и что пришло все а не часть)
     
  12. ostrov

    ostrov Гуру

    Поднимаете флажок и по нему последовательно вываливаетесь ото всюду.
     
  13. rkit

    rkit Гуру

    Как-то так правильно, если массив объявлен статически.
    Код (C++):
    uint8_t USART_Receive()
    {
      for(uint8_t i = 0; i < sizeof(Bincoming); i++)
      {
        sRX = millis();
        while ( !(UCSR0A & (1 << RXC0)) )
          if (millis() - sRX > pRX)
            return i;
        Bincoming[i] = UDR0;
      }
      digitalWrite(14, HIGH);
      return sizeof(Bincoming);
    }
     
  14. b707

    b707 Гуру

    именно для этого придуман оператор return. В самом первом коде поставьте его вместо goto lab
    Код (C++):
    void loop() {

    if (digitalRead(13)){return;}

    }