简体   繁体   中英

Use of extern in translation unit

extern int a;
int a = 1;

int main(void)
{
  return 0;
}

Is this UB? standard says in 6.2.2/7

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

The default linkage is extern . The extern specifier indicates that it might be defined and initialized in another translation unit, or the same one. The relative placement of an extern declaration does not matter, or they would be somewhat dangerous.

C99 TC2 §6.9.2/1

If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.

This is followed by an example:

int i1 = 1;  // definition, external linkage
…
extern int i1;  // refers to previous, whose linkage is external

This is perfectly defined behavior. And this is what the compiler would get after pre-processing after an header is included.

Your confusion seems to come that:

int a = 1;

has not internal linkage. At file-scope a has external linkage. It would have internal linkage if the static specifier was added.

The answer is yes and no.

If a is defined elsewhere in the same translation unit then yes, it's undefined behaviour.

If a is not defined anywhere else then int a=1 ; will be considered as the external definition of a (despite being defined in the same file). So it's not undefined.

Yes I think this will lead to (toolchain dependent) behaviour. Why?

The compiler generates a (for the linker) visible symbol 'a' while translating code like int a = ...; . The line extern int a; tells the compiler that every reference to 'a' will be be resolved by the linker.

This leaves two possible ways the compiler handles this contradiction: 1. By chance (as you only have one visible symbol called 'a') the linker binds the references to the created symbol 'a' of the same translation unit. 2. The compiler ignores the extern statement and binds directly to the a of this compilation unit.

An 'internal' symbol has to be declared as static ( static int a = ...; ) and then you'll get your UB i think.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM