Hacker News new | ask | show | jobs
by arcticbull 2377 days ago
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.

2 comments

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`.