Как объявить глобальную переменную в файле .h?

У меня есть файл библиотеки .h, в котором я хочу объявить глобальную переменную, которую можно будет прочитать в программном цикле и в файле .cpp библиотеки.

Вопрос в том, можно ли объявить переменную в файле .h и сделать ее глобальной?

, 👍5


2 ответа


Лучший ответ:

11
Файл

.h включается препроцессором компиляции в виде текста в файл .c или .cpp. Он включается так, как если бы вы заменили #include инструкцию препроцессора содержимым файла .h. (Файл Arduino .ino преобразуется в файл cpp перед предварительной обработкой.)

После включения файл cpp компилируется в объект (файл .o). Если файл cpp содержит определение переменной, она определена в этом объекте файле. Если ваш файл .h содержит определение переменной, она также находится в этом объектном файле.

Если два файла cpp включают файл .h с определением переменной, то переменная будет находиться в двух объектных файлах, и компоновщик завершит работу с ошибкой , из-за двух переменных с одинаковым именем. Если только один файл cpp/ino содержит переменную definition, тогда все в порядке. Это не очень хорошая практика, но иногда необходимый компромисс. (пример)

Чтобы одна глобальная переменная была доступна через файл .h, переменная должна быть только объявлена в файле .h и определена в одном файле cpp. Обычно это пара файлов .h и .cpp с одинаковым именем.

Пример глобальной переменной: Serial. Это глобальный объект типа HardwareSerial, объявленный в HardwareSerial.h как

внешний HardwareSerial Serial;

и определены в HardwareSerial0.cpp как

HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0);

Вы видите разницу? объявление содержит ключевое слово extern, а определение в данном случае содержит параметры для конструктора объекта. объявление с ключевым словом extern делает объект Serial видимым во всех файлах cpp, которые включают HardwareSerial.h (или включаемый файл, который включает HardwareSerial.h, например Arduino.h, включенный в преобразование ino в cpp).

,

4

Вы можете объявить переменную как статическую внутри функции inline, а затем просто вызвать эту функцию, чтобы получить ссылку на эту переменную. Пример:

inline int& getMyInteger()
{
    static int x;
    return x;
}

Это определение может находиться в файле заголовка, включенном в несколько файлов *.cpp, и любой вызов getMyInteger вернет ссылку на тот же объект. Вам не нужен ни extern, ни фактическое размещение переменной в какой-либо единице компиляции, как это необходимо для простой переменной области пространства имен. Этот трюк просто использует способность компоновщика дедуплицировать встроенные функции.

См. также: статические переменные во встроенной функции вопрос на StackOverflow.

,