One of the main reasons of using static
in the first place, is to make a variable local to the scope where it is declared. If you declare it at file scope (outside all functions), then it is local to the translation unit where it was declared. A translation unit means a .c file and all .h files that the .c file includes.
Meaning that if you have a static
variable in foo.h, then #include "foo.h"
from foo.c and bar.c, then you will end up with two different local copies of that variable: one inside the translation unit foo.h + foo.c, and another inside the translation unit foo.h + bar.c.
The solution is to never declare any variables inside header files. In addition to strange hiccups like the one described above, you can also run into various linker errors.
One sensible solution is to have the static Test_t test = TESTID;
inside test.c only. Then make setter and getter functions from test.h that other functions will use to access the variable.
The struct declaration can be placed in test.h if the getters return copies or const
pointers and other files should be allowed to access members directly. Or rather, that's fine for simpler stuff, but not recommended for more complex ADTs that should use proper private encapsulation.
(The only drawback with such a design is that it isn't thread-safe unless you implement thread safety inside the setter/getters, but that's another story.)