An identifier is visible where its declaration can be used. In C, that region is its scope: visibility begins at the declaration, not necessarily at the beginning of the surrounding block. A local declaration lasts through its enclosing block; a variable declared by a for construct is confined to that construct. Parameters are visible in their function body, while a function declared at file scope is visible from its declaration to the end of the file. TAKEAWAY: determine visibility from the declaration and its scope, not from a general notion that a name is “public.” section 2.2 section 13.2
Nested braces can change which declaration a name denotes. A declaration of x in an inner block shadows an outer x until that block ends. This does not make the outer object unusable: a pointer saved before the shadowing declaration can still refer to it. section 13.2
Listing 13.1 An example of shadowing with local variables
#include "c23-fallback.h"
void squareIt(double* p) [[__unsequenced__]] {
*p *= *p;
}
int main(void) { 1
double x = 35.0; 2
double* xp = &x;
{ 3
squareIt(&x); /* Refers to double x */
4
[[maybe_unused]] int x = 0; /* Shadow double x */
5
squareIt(xp); /* Valid use of double x */
6
}
7
squareIt(&x); /* Refers to double x */
}
Follow x through the inner block: the inner declaration changes which x can be named, while xp continues to point to the outer double object. section 13.2
Visibility also differs from object identity. In the extern example, a local definition creates a distinct object, but an extern declaration inside the if block refers to the existing file-scope object. The two declarations visible at different points need not designate different objects. section 13.2
Listing 13.2 An example of shadowing with an extern variable
#include <stdio.h> 1
unsigned i = 1;
int main(void) { 2
unsigned i = 2; /* A new object */
if (i) { 3
extern unsigned i; /* An existing object */
printf("%u\n", i); /* prints 1 */
} else {
printf("%u\n", i); /* prints 2 */
}
}
Compare the local unsigned i with the extern unsigned i inside the if block; the latter makes printf print the file-scope value, 1. section 13.2
A struct nested inside another struct does not acquire a private struct-declaration scope. The two struct declarations have the same scope: if declared at file scope, both are subsequently visible in the file; if declared inside a function, both are bound to the enclosing compound statement. TAKEAWAY: nesting a struct type in C does not by itself restrict that type’s visibility to the outer struct. section 6.3.3







