The keywords auto
, static
, extern
, register
, and _Thread_local
are referred to in the standard as storage class specifiers, but "objects" (this is the standardese term for what we usually call "variables") don't have storage classes. Instead they have linkage (external, internal, none) and storage duration (static, automatic, thread). In addition, any declaration of an object may or may not be a definition. The storage class specifiers, together with the scope at which the object is declared, and whether or not it has an initializer (int foo
vs int foo = 3
), control these properties. It's easiest to show how this works with a table:
sc-specifier scope initialized linkage storage duration is a definition
------------ ----- ----------- ------- ---------------- ---------------
auto file no [constraint violation]
auto file yes [constraint violation]
auto block no none automatic yes
auto block yes none automatic yes
none file no external static yes
none file yes external static yes
none block no none automatic yes
none block yes none automatic yes
static file no internal static yes
static file yes internal static yes
static block no none static yes
static block yes none static yes
extern file no external static no
extern file yes external static yes
extern block no external static no
extern block yes external static yes
The term "storage class specifier" is intentionally different from the terms "storage duration" and "linkage" to remind you that the specifiers don't give you independent control over the storage duration and linkage.
The language doesn't give you independent control over storage duration, linkage, and being a definition because the combinations that are unavailable don't make sense. Automatic storage duration only makes sense for variables declared at block scope, not being a definition only makes sense for variables with external linkage (because only they could be defined in another file), and so on.
I left register
and _Thread_local
out of the table because they are special. register
is just like auto
except that it also means you're not allowed to take the address of the object. _Thread_local
makes the storage duration of the variable be "thread" and doesn't change the linkage; it can be used by itself or with extern
or static
, but it's a constraint violation to combine it with "auto". I'm not sure what it does if you use it at block scope by itself.
static
keyword has some additional meanings.) – Aeratorstatic
doesn't have anything to do with the storage class static … confusing… why is the storage class then called that way and not something like “permanent”? – Plowmanauto
is only valid inside a function; ditto withregister
. You can't useauto
with a variable defined outside a function, any more than you can useregister
with such a variable. – Advocate