Как объявить глобальную переменную в файле .h?
У меня есть файл библиотеки .h, в котором я хочу объявить глобальную переменную, которую можно будет прочитать в программном цикле и в файле .cpp библиотеки.
Вопрос в том, можно ли объявить переменную в файле .h и сделать ее глобальной?
@Delta, 👍5
2 ответа
Лучший ответ:
.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).
Вы можете объявить переменную как статическую
внутри функции inline
, а затем просто вызвать эту функцию, чтобы получить ссылку на эту переменную. Пример:
inline int& getMyInteger()
{
static int x;
return x;
}
Это определение может находиться в файле заголовка, включенном в несколько файлов *.cpp
, и любой вызов getMyInteger
вернет ссылку на тот же объект. Вам не нужен ни extern
, ни фактическое размещение переменной в какой-либо единице компиляции, как это необходимо для простой переменной области пространства имен. Этот трюк просто использует способность компоновщика дедуплицировать встроенные
функции.
См. также: статические переменные во встроенной функции вопрос на StackOverflow.
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Что лучше использовать: #define или const int для констант?
- Функции со строковыми параметрами
- Как работать с аналоговыми контактами в цикле?
- Какие есть другие IDE для Arduino?
- Как использовать переменные и функции в нескольких файлах .ino
- Разница между void setup() и void setup(void)
- Будет ли .ino-скетч ардуино компилироваться непосредственно на GCC-AVR?