scope

Область видимости (scope) определяет, каким частям программы доступна переменная; глобальные видны во всём скетче, локальные — только внутри своего блока {}.

Полная статья

Описание

Область видимости (scope) — это правило, которое определяет, в каком месте программы переменная «видна» и может быть использована. В Arduino-скетчах, как и в C++, переменные делятся на глобальные и локальные.

Глобальная переменная объявляется вне любых функций — обычно в самом начале файла. Её видят setup(), loop() и все остальные функции в этом файле.

Локальная переменная объявляется внутри функции или блока кода (между фигурными скобками {}). Она существует только пока выполняется этот блок, а после выхода из него — исчезает. Обратиться к ней снаружи невозможно.

Пример кода

    int gPWMval;  // эта переменная видна из любой функции

    void setup() {
      // ...
    }

    void loop() {
      int i;    // "i" видна только внутри "loop"
      float f;  // "f" видна только внутри "loop"
      // ...

      for (int j = 0; j < 100; j++) {
        // переменная j доступна только внутри скобок цикла for
      }
    }

Где применяется

  • Счётчик в цикле — классический пример локальной переменной: int i в заголовке for нужна только внутри этого цикла и нигде больше.
  • Флаг состояния устройства — если несколько функций должны знать, включён ли мотор или в каком режиме работает устройство, удобнее хранить это в глобальной переменной.
  • Последние показания датчика — если setup() читает датчик и передаёт значение в loop() для отображения, глобальная переменная служит «мостом» между ними.
  • Обработчики прерываний — переменная, которую устанавливает ISR и проверяет loop(), должна быть глобальной (и объявленной как volatile).

Практические замечания

  • Не делайте переменную глобальной «на всякий случай». Чем уже область видимости, тем проще читать и отлаживать код: сразу понятно, кто и откуда может изменить значение.
  • Переменная в заголовке for доступна только внутри тела этого цикла. Попытка обратиться к ней после закрывающей скобки вызовет ошибку компиляции.
  • Одинаковые имена в разных областях не конфликтуют, но могут запутать. Если локальная переменная называется так же, как глобальная, внутри блока будет использоваться локальная — глобальная при этом не изменится. Такое «затенение» лучше избегать.
  • Если локальная переменная должна помнить своё значение между вызовами функции, используйте квалификатор static. Переменная останется локальной по видимости, но не будет уничтожаться при выходе из функции.
  • При отладке через Serial Monitor полезно помнить: если вы распечатываете переменную и получаете неожиданное значение, проверьте, не объявлена ли одноимённая переменная в локальной области — возможно, вы читаете не ту.

Полезные материалы