Files
2025-10-25 03:02:53 +03:00

158 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.2Storage class specifiers[dcl.stc]")
static
thread_local
extern
mutable
At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[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.2Storage class specifiers[dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and
the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1General[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.2Anonymous unions")))[.](#1.sentence-4)
The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[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.4Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3Explicit 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.2Storage 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.4Automatic 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.3Thread 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.7Structured 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.2Storage class specifiers[dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[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.7Structured binding declarations")), or
to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2Anonymous 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.2Static 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.3Thread storage duration"))[.](#4.sentence-3)
A static specifier can be
used in declarations of class members; [[class.static]](class.static "11.4.9Static members") describes its
effect[.](#4.sentence-4)
For the linkage of a name declared with a static specifier,
see [[basic.link]](basic.link "6.7Program 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.7Program 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.3Explicit instantiation[temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12Linkage specifications[dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage 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.4Class 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.5CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers"))[.](#9.sentence-1)
— *end note*]