[dcl.stc] # 9 Declarations [[dcl]](./#dcl) ## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.stc) ### 9.2.2 Storage class specifiers [dcl.stc] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L518) The storage class specifiers are [storage-class-specifier:](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") static thread_local extern mutable At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), except that thread_local may appear with static orextern[.](#1.sentence-2) If thread_local appears in any declaration of a variable it shall be present in all declarations of that entity[.](#1.sentence-3) If a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") of the declaration shall not be empty (except for an anonymous union declared in a namespace scope ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")))[.](#1.sentence-4) The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") in the list and not to any names declared by other specifiers[.](#1.sentence-5) [*Note [1](#note-1)*: See [[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation") for restrictions in explicit specializations and explicit instantiations, respectively[.](#1.sentence-6) — *end note*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L546) [*Note [2](#note-2)*: A variable declared without a [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") at block scope or declared as a function parameter has [automatic storage duration](basic.stc.auto#def:storage_duration,automatic "6.8.6.4 Automatic storage duration [basic.stc.auto]") by default[.](#2.sentence-1) — *end note*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L553) The thread_local specifier indicates that the named entity has thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#3.sentence-1) It shall be applied only to the declaration of a variable of namespace or block scope, to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or to the declaration of a static data member[.](#3.sentence-2) When thread_local is applied to a variable of block scope the[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#3.sentence-3) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L565) The static specifier shall be applied only to the declaration of a variable or function, to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#4.sentence-1) There can be nostatic function declarations within a block, nor anystatic function parameters[.](#4.sentence-2) A static specifier used in the declaration of a variable declares the variable to have static storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")), unless accompanied by thethread_local specifier, which declares the variable to have thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#4.sentence-3) A static specifier can be used in declarations of class members; [[class.static]](class.static "11.4.9 Static members") describes its effect[.](#4.sentence-4) For the linkage of a name declared with a static specifier, see [[basic.link]](basic.link "6.7 Program and linkage")[.](#4.sentence-5) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L584) The extern specifier shall be applied only to the declaration of a variable or function[.](#5.sentence-1) The extern specifier shall not be used in the declaration of a class member or function parameter[.](#5.sentence-2) For the linkage of a name declared with an extern specifier, see [[basic.link]](basic.link "6.7 Program and linkage")[.](#5.sentence-3) [*Note [3](#note-3)*: The extern keyword can also be used in[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") in such contexts[.](#5.sentence-4) — *end note*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L600) All declarations for a given entity shall give its name the same linkage[.](#6.sentence-1) [*Note [4](#note-4)*: The linkage given by some declarations is affected by previous declarations[.](#6.sentence-2) Overloads are distinct entities[.](#6.sentence-3) — *end note*] [*Example [1](#example-1)*: static char* f(); // f() has internal linkagechar* f() // f() still has internal linkage{ /* ... */ }char* g(); // g() has external linkagestatic char* g() // error: inconsistent linkage{ /* ... */ }void h();inline void h(); // external linkageinline void l();void l(); // external linkageinline void m();extern void m(); // external linkagestatic void n();inline void n(); // internal linkagestatic int a; // a has internal linkageint a; // error: two definitionsstatic int b; // b has internal linkageextern int b; // b still has internal linkageint c; // c has external linkagestatic int c; // error: inconsistent linkageextern int d; // d has external linkagestatic int d; // error: inconsistent linkage — *end example*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L642) The name of a declared but undefined class can be used in anextern declaration[.](#7.sentence-1) Such a declaration can only be used in ways that do not require a complete class type[.](#7.sentence-2) [*Example [2](#example-2)*: struct S;extern S a;extern S f();extern void g(S); void h() { g(a); // error: S is incomplete f(); // error: S is incomplete} — *end example*] [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L661) The mutable specifier shall appear only in the declaration of a non-static data member ([[class.mem]](class.mem "11.4 Class members")) whose type is neither const-qualified nor a reference type[.](#8.sentence-1) [*Example [3](#example-3)*: class X {mutable const int* p; // OKmutable int* const q; // error}; — *end example*] [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L674) [*Note [5](#note-5)*: The mutable specifier on a class data member nullifies aconst specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers"))[.](#9.sentence-1) — *end note*]