liveBook · Manning

Storage class

As explained in Modern C

A storage class specifier is a C declaration keyword that specifies an object's storage duration, linkage, or related declaration properties.

Consider a local variable hidden by a nested declaration: an inner int x can shadow an outer double x, while a pointer saved before the shadowing declaration still accesses the outer object. A storage class specifier helps describe such declarations through properties including scope, linkage, and storage duration. section 13.2

extern selects an existing object

With unsigned i = 1 at file scope and unsigned i = 2 inside main, the declaration extern unsigned i inside the if block refers to the existing file-scope object. The condition therefore prints 1, while the else branch refers to the local object and would print 2. The declaration changes which identifier is visible; it does not create a third object. section 13.2 section 13.2

Listing 13.1. An example of shadowing with local variables
 1     void squareIt(double* p) {
 2       *p *= *p;
 3     }
 4     int main(void) {
 5     double x = 35.0;
 6     double* xp = &x;
 7     {
 8       squareIt(&x);  /* Refers to double x */ 
 9       ...
10       int x = 0;     /* Shadow double x */ 
11       ...
12       squareIt(xp);  /* Valid use of double x */ 
13       ...
14     }
15     ...
16     squareIt(&x);    /* Refers to double x */ 
17     ...
18   }


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":1},{\"line\":0,\"ch\":2}],[{\"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\":13,\"ch\":0},{\"line\":13,\"ch\":1}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":1}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":1}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":1}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":1}],[{\"line\":0,\"ch\":7},{\"line\":0,\"ch\":11}],[{\"line\":3,\"ch\":16},{\"line\":3,\"ch\":20}],[{\"line\":0,\"ch\":21},{\"line\":0,\"ch\":27}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":13}],[{\"line\":5,\"ch\":7},{\"line\":5,\"ch\":13}],[{\"line\":7,\"ch\":37},{\"line\":7,\"ch\":43}],[{\"line\":9,\"ch\":34},{\"line\":9,\"ch\":40}],[{\"line\":11,\"ch\":40},{\"line\":11,\"ch\":46}],[{\"line\":15,\"ch\":37},{\"line\":15,\"ch\":43}],[{\"line\":1,\"ch\":1},{\"line\":1,\"ch\":2}],[{\"line\":11,\"ch\":1},{\"line\":11,\"ch\":2}],[{\"line\":2,\"ch\":1},{\"line\":2,\"ch\":2}],[{\"line\":4,\"ch\":18},{\"line\":4,\"ch\":19}],[{\"line\":12,\"ch\":1},{\"line\":12,\"ch\":2}],[{\"line\":3,\"ch\":1},{\"line\":3,\"ch\":2}],[{\"line\":13,\"ch\":1},{\"line\":13,\"ch\":2}],[{\"line\":3,\"ch\":7},{\"line\":3,\"ch\":10}],[{\"line\":9,\"ch\":9},{\"line\":9,\"ch\":12}],[{\"line\":3,\"ch\":11},{\"line\":3,\"ch\":15}],[{\"line\":0,\"ch\":7},{\"line\":0,\"ch\":11}],[{\"line\":3,\"ch\":16},{\"line\":3,\"ch\":20}],[{\"line\":4,\"ch\":1},{\"line\":4,\"ch\":2}],[{\"line\":14,\"ch\":1},{\"line\":14,\"ch\":2}],[{\"line\":0,\"ch\":21},{\"line\":0,\"ch\":27}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":13}],[{\"line\":5,\"ch\":7},{\"line\":5,\"ch\":13}],[{\"line\":7,\"ch\":37},{\"line\":7,\"ch\":43}],[{\"line\":9,\"ch\":34},{\"line\":9,\"ch\":40}],[{\"line\":11,\"ch\":40},{\"line\":11,\"ch\":46}],[{\"line\":15,\"ch\":37},{\"line\":15,\"ch\":43}],[{\"line\":5,\"ch\":1},{\"line\":5,\"ch\":2}],[{\"line\":15,\"ch\":1},{\"line\":15,\"ch\":2}],[{\"line\":0,\"ch\":21},{\"line\":0,\"ch\":27}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":13}],[{\"line\":5,\"ch\":7},{\"line\":5,\"ch\":13}],[{\"line\":7,\"ch\":37},{\"line\":7,\"ch\":43}],[{\"line\":9,\"ch\":34},{\"line\":9,\"ch\":40}],[{\"line\":11,\"ch\":40},{\"line\":11,\"ch\":46}],[{\"line\":15,\"ch\":37},{\"line\":15,\"ch\":43}],[{\"line\":6,\"ch\":1},{\"line\":6,\"ch\":2}],[{\"line\":16,\"ch\":1},{\"line\":16,\"ch\":2}],[{\"line\":7,\"ch\":1},{\"line\":7,\"ch\":2}],[{\"line\":17,\"ch\":1},{\"line\":17,\"ch\":2}],[{\"line\":8,\"ch\":1},{\"line\":8,\"ch\":2}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":2}],[{\"line\":3,\"ch\":7},{\"line\":3,\"ch\":10}],[{\"line\":9,\"ch\":9},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":2}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":2}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":2}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":2}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":2}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":2}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":2}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":2}]]"}
!@%STYLE%@!

Trace how a nested declaration shadows the identifier x without invalidating a pointer that still designates the outer object. section 13.2

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%@!

Compare a new block-scope definition with an extern declaration that makes an existing file-scope object visible. section 13.2

Static storage duration lasts for the entire program execution. File-scope definitions and block-scope variables declared static have this duration; such objects are always initialized, either explicitly or implicitly with zero. An extern declaration designates an object of static storage duration expected to be defined at file scope, possibly in another translation unit. section 13.2.1 section 13.2

How Modern C covers it

How deep it goes
Explains shadowing, extern object identity, static lifetime, and initialization, while deferring broader declaration details to a classification table.
Examples
Uses nested x declarations, a retained pointer, and file-scope and block-scope i declarations involving extern.
What it assumes
Assumes familiarity with C declarations, scopes, functions, pointers, and file scope.
What you can do after
Evaluate which object a declaration names and distinguish identifier visibility from object lifetime and usability.
How it connects
Connects storage classes with scope, linkage, lifetime, initialization, declarations, definitions, shadowing, and translation units.

Also explained in

Compare how 2 books explain storage class →

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.