3

I'm reading the source of a C project and am trying to discern why a particular use of extern is being used. (Note: This question is related but for C++, not C.) Say I have four header files that each declare an extern const struct:

extern const struct puppy fido;

This struct is defined in a source file like so:

extern const struct puppy fido;
static const struct puppy *puppies[] = { &fido };
const struct puppy fido = { "fido", 10, 10 };

Is there some kind of benefit to marking the variable declaration as extern in the source file, when those variables are defined in that very same source file?

Community
  • 1
  • 1
ybakos
  • 8,152
  • 7
  • 46
  • 74
  • I think this post may help: http://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files-in-c – Adriano Repetti May 19 '16 at 12:31
  • Please clarify, do I understand this correctly: you have 4 header files with extern declaration, and 1 .c file containing both an extern declaration and the definition? – Lundin May 19 '16 at 12:33
  • @Lundin That is correct. – ybakos May 19 '16 at 12:49
  • that `extern` definition should be in _one_ of your header files, and then that same header file also #included within the source file that actually holds the variable. – Alnitak May 19 '16 at 13:03

4 Answers4

4

The only advantage would be that any code between the declaration and the definition will be able to access the variable. Apart from that, the extern declaration in the same file is pointless.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    I think the `extern` is not needed anyway. But it certainly looks like a "*forward declaration*". – Iharob Al Asimi May 19 '16 at 12:35
  • 1
    Also, some feel it is good code organization to have declarations of all the static variables in the file together near the top, even if there isn't a specific reason for needing the 'forward declaration' – M.M May 19 '16 at 12:51
  • While the declaration enables accessing the variable before the definition, it does not answer the question about the use of `extern` in the declaration. – ybakos May 19 '16 at 13:20
2

Lundin is correct, that in this case extern does not affect visibility of fido in other source files. In your example code, it is used as a forward declaration.

Relevant part from C99 standard, section 6.2.2:

4) For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

5) If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external

In C++, behavior would be different, because variables declared with const are implicitly static. In C++, you are required to declare the variable with extern the first time, or other compilation units would not find it.

C++98 standard, section 3.5.3:

A name having namespace scope (3.3.5) has internal linkage if it is the name of

— an object, reference, function or function template that is explicitly declared static or,

— an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage;

VLL
  • 9,634
  • 1
  • 29
  • 54
  • 2
    FWIW, declaring internal variables without static is flagged to be an obsolete feature in C. C11 6.11.2 Linkages of identifiers: "Declaring an identifier with internal linkage at file scope without the static storage class specifier is an obsolescent feature." – Lundin May 19 '16 at 13:02
  • 1
    this is a C question, why do you keep talking about other languages – M.M May 19 '16 at 15:36
  • 3
    @M.M Someone might search this in future and not realize C and C++ work in a different way. – VLL May 19 '16 at 15:45
0

Sometimes, when you write a source file, you just want a piece of a header file, not the whole thing.

Repeating the extern declaration in the source file allows you not to include the header file in that specific source file.

This is not necessarily a good practice.

Myst
  • 18,516
  • 2
  • 45
  • 67
-1
extern const struct puppy fido;
// ...
const struct puppy fido = { "fido", 10, 10 };

If const struct puppy fido = { "fido", 10, 10 }; is compiled in 2 different .c files, it will fail. There should be #ifndef and endif before and after the const struct puppy fido = { "fido", 10, 10 }; in order to include it once.

A good practice (globals variables have to be avoided in general) is to declare with extern in the .h files, and to put the definition of the variable in a .c file.

  • ifndef/endif does not help with issues involving compilation across 2 different c files . I'm not sure what you are trying to say – M.M May 19 '16 at 12:51
  • @M.M : it supposes that in the c file you use `#define DECLARE_MY_CONST_FIDO`, and then include this header. The `const struct...` will be written only in this file. If the const declaration is in the file without `#ifdef DECLARE_MY_CONST_FIDO`, it's sure it will fail if the file is included in several .c files. – Pierre Emmanuel Lallemant May 19 '16 at 13:34
  • ok maybe include example code in your answer. that's an unusual technique so people won't know what you are talking about – M.M May 19 '16 at 15:35