A local declaration can hide a name without ending the object behind it. In the shadowing example, an inner `int x` hides an outer `double x`, yet a pointer saved earlier still lets `squareIt` modify the outer object. Visibility of an identifier and lifetime of an object are different questions. 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%@!
Follow `xp` through the inner block: it still points to the outer `double x` while the name `x` denotes the inner `int`. section 13.2
TAKEAWAY: An object has a lifetime with a beginning and an end. Accessing it outside that interval has undefined behavior. Where its lifetime begins and ends depends on how its storage is created, not merely on whether a name is visible. section 13.2
C distinguishes four storage durations:
- Static: file-scope objects and block-scope variables declared `static` live for the whole program execution. They are initialized before application code runs, even if their identifiers have narrow visibility. section 13.2.1
- Automatic: a local object’s lifetime follows its relevant scope during execution. Entering that scope starts an ordinary automatic object’s lifetime; a new loop iteration defines a new instance of a local object. section 13.3 section 17.3
- Allocated: calls such as `malloc` explicitly determine storage duration. section 13.2
- Thread: storage duration is bound to a thread of execution. section 13.2
A pointer can retain an address after the object there has died; retaining the address does not extend the lifetime. For a compound literal created as the body of a `while` statement, dereferencing a saved pointer after the loop is invalid. Repeating an assignment by `goto` within the surrounding block instead leaves the compound-literal object alive until that block is left. These forms are not interchangeable. section 17.3
1 size_t* ip = 0
2 while(something)
3 ip = &(size_t){ fun() }; /* Life ends with while */
4 /* Good: resource is freed */
5 printf("i is %d", *ip) /* Bad: object is dead */
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":19}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":1}],[{\"line\":1,\"ch\":4},{\"line\":1,\"ch\":9}],[{\"line\":2,\"ch\":56},{\"line\":2,\"ch\":61}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":19}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":1}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":1}],[{\"line\":4,\"ch\":4},{\"line\":4,\"ch\":10}]]"}
!@%STYLE%@!
The `while` version saves an address, then attempts to read the compound literal after its lifetime has ended. section 17.3
1 size_t* ip = 0
2 RETRY:
3 ip = &(size_t){ fun() }; /* Life continues */
4 if (condition) goto RETRY;
5 /* Bad: resource is blocked */
6 printf("i is %d", *ip) /* Good: object is alive */
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":19}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":1}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":19}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":1}],[{\"line\":2,\"ch\":42},{\"line\":2,\"ch\":44}],[{\"line\":3,\"ch\":4},{\"line\":3,\"ch\":6}],[{\"line\":3,\"ch\":19},{\"line\":3,\"ch\":23}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":1}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":1}],[{\"line\":5,\"ch\":4},{\"line\":5,\"ch\":10}]]"}
!@%STYLE%@!
Compare the `goto` version: the compound literal remains alive at the final read, though its resources remain occupied longer. section 17.3
TAKEAWAY: Do not infer lifetime solely from the point at which a definition is executed. A `goto` example revisits a compound literal and obtains equal, valid pointers on successive passes; its specified result depends on the enclosing block’s lifetime rule, not on a fresh object being created at each jump. section 13.3







