7

C11 specifies in section 6.7 which declarations are also definitions:

A definition of an identifier is a declaration for that identifier that:
— for an object, causes storage to be reserved for that object;
[...]

I didn't find a comprehensive list of which object declarations cause storage to be reserved. Intuitively it is clear to me, but I wasn't able to get this information out of the C11 standard.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Manuel Jacob
  • 1,897
  • 10
  • 21
  • Huh? As I read it, *declarations* don't cause anything to be reserved. – Eugene Sh. Aug 15 '17 at 13:41
  • 1
    any that doesn't use the `extern` storage class. –  Aug 15 '17 at 13:42
  • @EugeneSh. each definition is at the same time a declaration, the opposite isn't true. –  Aug 15 '17 at 13:42
  • @FelixPalmen So the question is "which declaration is a definition". – Eugene Sh. Aug 15 '17 at 13:43
  • @EugeneSh. in a nutshell, yes. Limiting this to declarations of variables, the answer is my comment above. –  Aug 15 '17 at 13:44
  • @FelixPalmen Well.. what about tentative definitions? http://en.cppreference.com/w/c/language/extern – Eugene Sh. Aug 15 '17 at 13:44
  • @FelixPalmen Except when it's a *tentative definition*. For example a global variable without `extern` *might* be a definition or it might be a declaration. – Some programmer dude Aug 15 '17 at 13:45
  • @EugeneSh. well, they depend on context ... write an answer if you like ;) –  Aug 15 '17 at 13:45
  • I'll give a chance to someone else :) – Eugene Sh. Aug 15 '17 at 13:47
  • @BoPersson I don't think this is a duplicate. The accepted answer says "The text which specifies that int a; is a definition is elsewhere.". But this is one part of what I was asking for. – Manuel Jacob Aug 15 '17 at 13:54
  • @BoPersson this is not a duplicate, it asks whether a definition seizes to be a definition when the compiler optimizes the object away (to which the answer is: **no**, because in terms of the abstract machine, this is not relevant). This question here asks for a complete overview of what *defines* an object and what only *declares* one. –  Aug 15 '17 at 14:10
  • @FelixPalmen Isn't `extern int foo = 42;` a definition? – melpomene Aug 15 '17 at 14:15
  • @melpomene yes, it's an external definition. The comment was indeed too short, there mustn't be an initializer as well. –  Aug 15 '17 at 14:15

1 Answers1

6

There's no definitive list because the standard just describes what are definitions and it's not in a single place. I'll try to sum it up here. I'll only use the type int here without any qualifiers (like const) for consistency.

  • If you add an initializer to a declaration, it's always a definition:

    int x = 1;
    
  • Without an initializer, the following are definitions when they're in function scope:

    int x;
    auto int x;        // auto is the default anyways
    register int x;    // register is just a hint, but would be "storage" as well
    static int x;      // also reserves storage, but with static duration
    
  • In file scope, the rules are a bit more complicated; the following are tentative definitions:

    int x;
    static int x;
    

    The wording of the standard (§6.9.2p2) is:

    A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0

    so this means that they eventually "become definitions" if they are not found to refer to another definition.

  • With the storage class extern and without an initializer, you don't have a definition:

    extern int x;     // <- not a definition
    

AFAIK, this should be the complete set of rules. Please feel free to edit/comment if I forgot something.

  • There also is the case of `_Thread_local` declarations, that seem to follow similar rules as for tentative definitions, only that the standard only says so in 6.7.9. Probably they don't want to list it as tentative definition, because such a `_Thread_local` declaration effectively declares one object per thread. – Jens Gustedt Aug 15 '17 at 15:32
  • Obviously they are not objects but it is perhaps worth noting the somewhat confusing overloaded use of `extern` in the context of inline function instantiations. Frankly I do not quite understand why the semantics of plain `inline` and `extern inline` weren't reversed. – doynax Aug 15 '17 at 17:11