Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a declaration of a variable inside a block also a definition?

The C11 standard specifies in section 6.7/5 which declarations are also definitions:

C11 6.7/5

A definition of an identifier is a declaration for that identifier that:

— for an object, causes storage to be reserved for that object;

(...)

So is a declaration of a variable inside a block also a definition? For example:

void Bla(void) {
    int a; // Is this declaration also a definition?
}

I have found the following two answers on stackoverflow, which state that declarations of variables inside blocks are also definitions:

  • https://stackoverflow.com/a/4769638
  • https://stackoverflow.com/a/45695028/9771101

However, the answer provided by "Michael Burr" refers to 6.2.2/2 "Linkages of identifiers" in order to explain that variable declarations in block scope are also definitions. For me, his reference does not answer my question. The answer in the second link does not provide any reference to the C standard. Is there any other paragraph in the C standard which can be used as a reference to confirm those answers?

Please provide a reference to the C standard.

like image 201
Sinushyperbolikus Avatar asked Dec 17 '22 21:12

Sinushyperbolikus


2 Answers

Yes, a declaration of an "object" (the C standard avoids using the word "variable") at block scope is a definition, except when the declaration of that object uses the storage-class specifier extern, in which case it is not a definition.

Here is how to see that from the standard (all references are to N1570, which is the closest approximation to the official text of C2011 that is publicly available at no charge):

first, 6.2.2p6 says

the following identifiers have no linkage: ... a block scope identifier for an object declared without the storage-class specifier extern.

second, 6.7p5 says

A definition of an identifier is a declaration for that identifier that: * for an object, causes storage to be reserved for that object;

and finally, 6.2.4 which you will need to read in its entirety, but the most important bits are in paragraph 5 and 6:

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration ... its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.

So, if you declare an object at block scope without extern, it has no linkage. An object with no linkage has automatic storage duration, unless it was declared with static, in which case it has static storage duration instead, see the parts of 6.2.4 I didn't quote. An object with automatic storage duration has storage reserved for it upon entry to the block it was declared within, and an object with static storage duration has storage reserved for it at program start (again, see the parts of 6.2.4 I didn't quote). Therefore, any declaration of an object that gives it no linkage is a definition.

(A declaration of an object at block scope with extern gives it external linkage and is not a definition. If you don't see why that is after reading through all of the sections I quoted and also 6.9, please ask a new question specifically about that.)

like image 137
zwol Avatar answered May 09 '23 16:05

zwol


Section 6.2.2p6 of the C standard states:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.

The part that's missing is section 6.2.2p6:

The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifier extern.

A variable declared inside of a block that does not have a storage class specifier (i.e. static or extern) has no linkage, and each declaration of a variable with no linkage is a unique object. Because the declaration is unique, it also qualifies as a definition.

See also section 6.7p7:

If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer; in the case of function parameters (including in prototypes), it is the adjusted type (see 6.7.6.3) that is required to be complete.

like image 34
dbush Avatar answered May 09 '23 15:05

dbush