liveBook · Manning

Declaration

As explained in Modern C

A declaration is a C construct that specifies the kind of entity an identifier refers to without necessarily defining the entity or providing its value.

int main(void);
double A[5];
size_t i;


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":3}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":0,\"ch\":9},{\"line\":0,\"ch\":13}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":6}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":6}]]"}
!@%STYLE%@!

Start with three declarations: int main(void);, double A[5];, and size_t i;. Each gives the compiler a name and properties of what that name denotes. section 2.2

A declaration specifies what an identifier represents before the identifier is used. The type comes first in these examples: main declares a function returning int, A declares an array of five double items, and i declares a variable of type size_t. Parentheses mark the function declaration; brackets mark the array declaration. Keywords differ from identifiers: they are predefined by C and are not declared. section 2.2

TAKEAWAY: All identifiers must be declared. For a variable, keep four things separate: its identifier (name), type (specification), object (the item that holds a value), and value (its contents). A declaration alone need not supply that value or say where the object can be found. section 2.2 section 2.3

Adding a definition

Compare size_t i; with size_t i = 0;. The initializer gives i an initial value and, in this case, the declaration also defines its object: storage is provided for that value. Likewise, int main(void); declares a function, while int main(void) followed by a body in braces defines it. TAKEAWAY: A declaration specifies an identifier; a definition specifies the associated object or function. section 2.3 section 2.1

Listing 13.2. An example of shadowing with an extern variable
 1   #include <stdio.h>
 2
 3   unsigned i = 1;
 4
 5   int main(void) {
 6     unsigned i = 2;        /* A new object */ 
 7     if (i) {
 8       extern unsigned i;   /* An existing object */ 
 9       printf("%u\n", i);
10     } else {
11       printf("%u\n", i);
12     }
13   }


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":1},{\"line\":0,\"ch\":2}],[{\"line\":2,\"ch\":18},{\"line\":2,\"ch\":19}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":1}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":1}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":1}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":1}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":13}],[{\"line\":1,\"ch\":1},{\"line\":1,\"ch\":2}],[{\"line\":5,\"ch\":20},{\"line\":5,\"ch\":21}],[{\"line\":11,\"ch\":1},{\"line\":11,\"ch\":2}],[{\"line\":2,\"ch\":1},{\"line\":2,\"ch\":2}],[{\"line\":12,\"ch\":1},{\"line\":12,\"ch\":2}],[{\"line\":2,\"ch\":5},{\"line\":2,\"ch\":13}],[{\"line\":5,\"ch\":7},{\"line\":5,\"ch\":15}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":24}],[{\"line\":3,\"ch\":1},{\"line\":3,\"ch\":2}],[{\"line\":4,\"ch\":1},{\"line\":4,\"ch\":2}],[{\"line\":4,\"ch\":5},{\"line\":4,\"ch\":8}],[{\"line\":8,\"ch\":11},{\"line\":8,\"ch\":14}],[{\"line\":10,\"ch\":11},{\"line\":10,\"ch\":14}],[{\"line\":4,\"ch\":9},{\"line\":4,\"ch\":13}],[{\"line\":4,\"ch\":14},{\"line\":4,\"ch\":18}],[{\"line\":5,\"ch\":1},{\"line\":5,\"ch\":2}],[{\"line\":2,\"ch\":5},{\"line\":2,\"ch\":13}],[{\"line\":5,\"ch\":7},{\"line\":5,\"ch\":15}],[{\"line\":7,\"ch\":16},{\"line\":7,\"ch\":24}],[{\"line\":6,\"ch\":1},{\"line\":6,\"ch\":2}],[{\"line\":6,\"ch\":7},{\"line\":6,\"ch\":9}],[{\"line\":7,\"ch\":1},{\"line\":7,\"ch\":2}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":24}],[{\"line\":8,\"ch\":1},{\"line\":8,\"ch\":2}],[{\"line\":8,\"ch\":9},{\"line\":8,\"ch\":15}],[{\"line\":10,\"ch\":9},{\"line\":10,\"ch\":15}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":2}],[{\"line\":9,\"ch\":9},{\"line\":9,\"ch\":13}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":2}],[{\"line\":8,\"ch\":9},{\"line\":8,\"ch\":15}],[{\"line\":10,\"ch\":9},{\"line\":10,\"ch\":15}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":2}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":2}]]"}
!@%STYLE%@!

Follow the three declarations of i. The file-scope unsigned i = 1; defines one object, and the local unsigned i = 2; defines another. Inside the if block, extern unsigned i; declares the existing file-scope object rather than creating a third; the printf there therefore prints 1. section 13.2

A name is visible within its scope starting at its declaration, but a declaration in a subordinate scope can shadow the same name. Do not equate a newly visible declaration with a new object: the extern declaration above names an existing one. Conversely, each variable definition creates a distinct object. section 13.2

How Modern C covers it

How deep it goes
Works through function, array, variable, initializer, and extern examples, while deferring fuller complications of declarations and definitions.
Examples
Compares declarations of main, A, and i, then traces three declarations of i that denote two objects.
What it assumes
Introduces identifiers, types, arrays, objects, and values before extending the distinction to scope and extern.
What you can do after
Diagnose/debug with it whether a declaration introduces a distinct object or names an existing one under extern and shadowing.
How it connects
Connects declarations to identifiers, types, definitions, initialization, scope, shadowing, and storage duration.

Also explained in

Compare how 2 books explain declaration →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.