How to declare a global variable in the .h file?

.h file is included by the compilation preprocessor as text into the .c or .cpp file. It is included as if you would replace the #include preprocessor instruction with the content of the .h file. (The Arduino .ino file is converted to cpp file before preprocessing.)

After the inclusion the cpp file is compiled to 'object' (.o file). If the cpp file contains a variable definition the variable is defined in this object file. If your .h file contained a variable definition, the it is also in this object file.

If two cpp files included the .h file with the definition of the variable, then the variable will be in two object files and the linker will exit with an error, because of two variables with the same name. If only one cpp/ino files includes the variable definition, then it is OK. It is not a good practice, but sometimes a necessary compromise. (example of it)

To have one global variable made accessible by a .h file, the variable should be only declared in the .h file and be defined in one cpp file. Usually it is a pair of .h and .cpp file with same name.

An example of global variable is Serial. It is a global object of type HardwareSerial declared in HardwareSerial.h as

extern HardwareSerial Serial;

and defined in HardwareSerial0.cpp as

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

Do you see the difference? The declaration has the keyword extern and the definition has in this case parameters for the constructor of the object. The declaration with extern keyword makes object Serial visible in all cpp files which include HardwareSerial.h (or an include file which includes HardwareSerial.h like Arduino.h included by ino to cpp conversion).


You can declare the variable as a static variable inside an inline function, and then just call this function to get a reference to this variable. Example:

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

This definition can be in a header file, included into multiple *.cpp files, and any call to getMyInteger will return reference to the same object. You don't need any extern, nor to actually put the variable in any compilation unit as you would need with a simple namespace-scope variable. This trick just uses the linker's ability to de-duplicate inline functions.

See also: static variables in an inlined function question on StackOverflow.