1

I'm rewriting someone's code who had a global variable that is useful during initialization when Java makes it's callbacks into C, and just after. It appears they have declared this variable in several places with an extern prefix and once without. I don't really see why they would do this to a global variable (prefixed g_) when I would rather call it static and declare it just once.

Would I be able to do this or does static have negative connotations for thread safety in this context? The bulk of my code is C++ but there is some extern 'C' stuff like those functions Java calls into.

Currently I'm not using extern or static but I'm inclined to believe this is why I'm getting linking errors.

John
  • 6,433
  • 7
  • 47
  • 82

3 Answers3

4

static does not prevent a variable from being duplicated during the compilation of multiple compilation units. When you link those compilation units, they will end up seeing different "instances" of the same variable. In other words, each one will see its own copy.

The usefulness of extern is exactly to avoid this duplication. You declare the global (non-static) variable in an implementation file (.c) and declare it as extern on a given header file (.h) to be included by every source file that depends on it.

jweyrich
  • 31,198
  • 5
  • 66
  • 97
  • This sounds good and familiar. Thanks. Do you think it acceptable to put the (non-`external` qualified) declaration in `.cpp` file as there is no `.c` file anywhere? Yep, works, thanks very much @jweyrich – John Oct 20 '14 at 23:53
  • Cool! Sure, .cpp and .c are _equivalent_ in this aspect. – jweyrich Oct 21 '14 at 10:37
2

You can have global variables in C++ just like you can in C. Global variables constitute shared state, so just as in C, or in any language for that matter, if you access shared state from multiple threads concurrently (with at least one mutable access), you have to provide synchronization.

The extern "C" linkage specification is only necessary if you want to access the same variable from multiple translation units compiled in different languages that all use C linkage rules.

(Unlike in C, C++ global variables can have non-trivial initialization, which brings some new issues of ordering. But that shouldn't matter.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I see, I'm afraid I didn't word my question very well, I'm getting linker errors which appear to name this variable. That `exern "C"` was just for my java callbacks, I'd not elect it, nor `extern` for variables, I suppose it was done with some linker flags in mk files to ensuer all the compilation units use C linkage rules? I'm sure it worked yesterday though – John Oct 20 '14 at 23:36
2

You mixing extern, extern "C" and static

When declaring a regular variable or function in the global scope, the compiler expose it as a "public symbol"

when you use the extern before the variable declaration you specify it is a public symbol declared in other file. if you won't use the extern you'll get link error said the variable already defined.

The static keyword before a declaration do quite the opposite thing: it prevent the symbol from been public, therefore, it known only where it been declared (or included) and can't been externed. that is why you won't get the "already defined" link error when you declare the same static variable twice, and it actually will be declared twice.

and finally the extern "C" make variables been published in the C convention not in the C++ convention. the main difference is what called "overloading". in C++ several function can have the same name, with different arguments types, therefore need a convention to keep the types in the function name. in C the name as is is the public symbol name. you should use it when you wan't to make C++ function usable from C, or any other language, or maybe even from other C++ compiler version.

SHR
  • 7,940
  • 9
  • 38
  • 57