Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The extern class specifier

Tags:

c

If I have an external variable like this:

int a;

is right that declaration is equals to:

extern int a = 0;

and not equals to:

extern int;

Is it the same as local variable where write something like this:

int local;

is equals to:

auto int local;

In both cases does the compiler put, as default, the specifier extern or auto?

like image 368
xdevel2000 Avatar asked Apr 15 '26 05:04

xdevel2000


1 Answers

The rules for linkage and external definitions are a little odd, partly for historic reasons (cf. for example this C89 rationale). The rules for objects (they are different for function declarations) are:

At file scope:

  • auto and register are not allowed, a diagnostic is required1).
  • static means internal linkage2) and the declaration is a (tentative) definition3).
  • extern means linkage as already declared, if none is declared, external linkage4).
  • No storage-class specifier means external linkage5) and the declaration is a (tentative) definition6).
  • If multiple declarations disagree on linkage, the behaviour is undefined7) (Gcc aborts compilation, as do most compilers, I guess).

A tentative definition means, the object will be defined in the same translation unit, if there is no explicit definition, 0 is assumed.8) Multiple explicit definition are a constraint violation for identifiers with internal linkage; for identifiers with external linkage, the behaviour is undefined (Gcc aborts compilation).9)

The first two examples are mostly, but not exactly equivalent.

int a;

a has external linkage. The declaration is a tentative definition; if no explicit initialization follows, it is initialized to 0. If there was another declaration static int a;, the behaviour would be undefined.

extern int a = 0;

This, on the other hand, declares a to have external linkage only if either an external declaration is already visible or none is visible. If this was followed by a static declaration of a, the behaviour was undefined; if this was preceeded by one, the linkage would be internal. This declaration also initializes a to 0, no other explicit definition is allowed to appear in the translation unit.

extern int a;

(I assumed extern int a; instead of extern int;. If you really meant the latter: That’s a constraint violation.)

This is an (external, if no other declaration is visible) declaration without definition. Usually, the definition appears in another translation unit. It must appear somewhere if the identifier is used in an expression where it is evaluated.

At block scope:

  • extern means the same as at file scope, except there is no tentative definition. No initialization is allowed.10)
  • static means no linkage (but static storage-duration).11) If there is no initialization, it is initialized to 0 (once, at program startup).12)
  • auto or none means no linkage. If there is no initialization13), the value of the variable is indeterminate, reading such a value is undefined (not exactly, but practically).
  • register is the same like auto, but it’s a constraint violation to take its address.
  • No re-declaration is allowed for identifiers (denoting an object) with no linkage.14)

Thus, the last two examples are equivalent.

The two storage-class specifiers not mentioned here are typedef and (since C11) _Thread_local.15)

References to C11 (n1570):

1) 6.9 p2. 2) 6.2.2 p3. 3) 6.9.2 p2. 4) 6.2.2 p4. 5) 6.2.2 p5. 6) 6.9.2 p2. 7) 6.2.2 p7 8) 6.9.2 p2. 9) 6.9 p3 and p5. 10) 6.2.2 p4 and 6.7.9 p5. 11) 6.2.2 p6. 12) and 13) 6.7.9 p10. 14) 6.7 p3. 15) cf. 6.7.1.

like image 131
mafso Avatar answered Apr 16 '26 18:04

mafso