liveBook · Manning

Automatic object

As explained in Modern C

An automatic variable is a C variable whose storage is created on entry to its enclosing block and released when execution leaves that block.

A local variable normally exists while execution is inside its enclosing block. Enter the block again through a recursive call, and a separate instance exists for that call. TAKEAWAY: For an ordinary automatic object, lifetime follows execution of its block—not the point at which its definition is first reached. section 13.2.2 section 13.3

Block-scope variables declared without static have automatic storage duration; auto is the default, and register is another declaration option. Block-scope compound literals and some temporary results of function calls also qualify. Variable-length arrays (VLAs) and temporary objects need separate lifetime rules. section 13.2.2

A jump past a compound literal

In fgoto(2), a goto returns to a label above the compound literal. The second printed line reports that p and q are equal and that *p is 1. Reaching the label before reaching the literal’s expression again does not, by itself, end the block-scope object’s lifetime. The example separates an object’s lifetime from the execution that supplies its value. section 13.3

Listing 13.3. A contrived example for the use of a compound literal
 3   void fgoto(unsigned n) {
 4     unsigned j = 0;
 5     unsigned* p = 0;
 6     unsigned* q;
 7    AGAIN:
 8     if (p) printf("%u: p and q are %s, *p is %u\n",
 9                   j,
10                   (q == p) ? "equal" : "unequal",
11                   *p);
12     q = p;
13     p = &((unsigned){ j, });
14     ++j;
15     if (j <= n) goto AGAIN;
16   }


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

Follow the label, pointer assignments, and compound literal to see why the jump makes lifetime—not just statement order—the question. section 13.3

Storage and initialization are different concerns. In one unoptimized machine-code example, function entry reserves space for automatic objects with a few instructions; some are then initialized, while others remain uninitialized until later. That implementation illustrates the rule, not a required machine layout. For a non-array local in performance-critical code, register also prevents taking its address with &, helping expose potential aliasing. section 13.5 section 13.2.2

How Modern C covers it

How deep it goes
Defines ordinary lifetimes, works through a compound-literal case, and illustrates storage setup; sets aside separate VLA and temporary-object rules.
Examples
Uses a goto-driven compound literal and its printed pointer comparison, then contrasts unoptimized and optimized assembler versions.
What it assumes
Assumes familiarity with local variables and pointers while introducing goto and labels for the worked case.
What you can do after
Evaluate/understand when an ordinary local object exists without mistaking its declaration or initialization for the start of its lifetime.
How it connects
Connects block scope and recursion to compound literals, register declarations, aliasing, and initialization.

Also explained in

Compare how 2 books explain automatic object →

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.