They have different semantics. The static one can only be referenced in the current translation unit, whereas the non-static one is a global which can be referenced from any translation unit.
The problem is that in the header-only case defining "int a" means you can only import the header from a single source file. With "static int a" the visibility is wrong. And if you did "extern int a" linking would fail because the symbol is never assigned to a translation unit.
Header-only libraries sometimes require you to define those externs in exactly one "impl" file, which you compile and link to your artifact. Something like this:
// libfoo_impl.c
// or in some other translation unit, such as main.c
#define LIBFOO_IMPL
#include "vendor/libfoo.h"
// main.c
#include "vendor/libfoo.h"
int main() {
foo_inc();
printf("%d\n", foo_count);
return 0;
}
// vendor/libfoo.h
#pragma once
extern int foo_count;
void foo_inc() {
foo_count += 1;
}
#ifdef LIBFOO_IMPL
int foo_count = 0;
#endif
main.c and libfoo_impl.c both include libfoo.h, which declares foo_count with the right linkage, but the variable is only defined once, in whichever translation unit defines LIBFOO_IMPL.
Occasionally you'll find a header library which supports this _IMPL paradigm as an option to avoid inlining its functions in every translation unit that calls them.
You're misunderstanding. I'm saying you can have multiple identical `int a;` across multiple translation units and it will point by default to a single global variable across the program. So you can include a single header from multiple places, and you just get a single shared global variable, if the header contains `int a`.
The problem is that in the header-only case defining "int a" means you can only import the header from a single source file. With "static int a" the visibility is wrong. And if you did "extern int a" linking would fail because the symbol is never assigned to a translation unit.