Speicherklassenspezifizierer
Definieren Sie Speicherdauer und Bindung von Objekten und Funktionen
auto- automatische Dauer und keine Bindungregister- automatische Dauer und keine Bindung; die Adresse dieser Variablen kann nicht genommen werdenstatic- statische Dauer und interne Bindung (es sei denn, auf Blockebene)extern- statische Dauer und externe Bindung (es sei denn, bereits als intern deklariert)
|
(seit C11) |
Inhalt |
[bearbeiten] Erklärung
Speicherklassenspezifizierer erscheinen in Deklarationen und zusammengesetzten Literalausdrücken(seit C23). Höchstens ein Spezifizierer darf verwendet werden, außer dass _Thread_local(bis C23)thread_local(seit C23) mit static oder extern kombiniert werden kann, um die Bindung anzupassen(seit C11). Die Speicherklassenspezifizierer bestimmen zwei unabhängige Eigenschaften der von ihnen deklarierten Namen: Speicherdauer und Bindung.
_Alignas(bis C23)alignas(seit C23)(seit C11) und register-Arrays nicht in Zeiger konvertiert werden.|
5) _Thread_local(bis C23)thread_local(seit C23) zeigt die Thread-Speicherdauer an. Sie kann nicht mit Funktionsdeklarationen verwendet werden. Wenn sie bei einer Objektdelkaration verwendet wird, muss sie bei jeder Deklaration desselben Objekts vorhanden sein. Wenn sie bei einer Deklaration auf Blockebene verwendet wird, muss sie entweder mit static oder extern kombiniert werden, um die Bindung zu bestimmen. |
(seit C11) |
Wenn kein Speicherklassenspezifizierer angegeben ist, sind die Standardeinstellungen
- extern für alle Funktionen
- extern für Objekte auf Dateiebene
- auto für Objekte auf Blockebene
Für jede Struktur oder Union, die mit einem Speicherklassenspezifizierer deklariert wird, gilt die Speicherdauer (aber nicht die Bindung) rekursiv für ihre Member.
Funktionsdeklarationen auf Blockebene können extern oder gar keinen Spezifizierer verwenden. Funktionsdeklarationen auf Dateiebene können extern oder static verwenden.
Funktionsparameter können keine Speicherklassenspezifizierer außer register verwenden. Beachten Sie, dass static eine spezielle Bedeutung bei Funktionsparametern vom Array-Typ hat.
[bearbeiten] Speicherdauer
Jedes Objekt hat eine Eigenschaft namens Speicherdauer, die die Lebensdauer des Objekts begrenzt. Es gibt vier Arten von Speicherdauer in C:
- automatische Speicherdauer. Der Speicher wird zugewiesen, wenn der Block, in dem das Objekt deklariert wurde, betreten wird, und freigegeben, wenn er auf irgendeine Weise verlassen wird (goto, return, Erreichen des Endes). Eine Ausnahme bilden VLAs; ihr Speicher wird zugewiesen, wenn die Deklaration ausgeführt wird, nicht beim Betreten des Blocks, und freigegeben, wenn der Gültigkeitsbereich des Blocks verlassen wird, nicht beim Verlassen des Blocks(seit C99). Wenn der Block rekursiv betreten wird, erfolgt eine neue Zuweisung für jede Rekursionsebene. Alle Funktionsparameter und nicht-static-Objekte auf Blockebene haben diese Speicherdauer, ebenso wie zusammengesetzte Literale, die auf Blockebene verwendet werden(bis C23)
- statische Speicherdauer. Die Speicherdauer erstreckt sich über die gesamte Ausführung des Programms, und der im Objekt gespeicherte Wert wird nur einmal vor der main-Funktion initialisiert. Alle als static deklarierten Objekte und alle Objekte mit interner oder externer Bindung, die nicht als _Thread_local(bis C23)thread_local(seit C23) deklariert sind(seit C11) haben diese Speicherdauer.
|
(seit C11) |
- Zugewiesene Speicherdauer. Der Speicher wird auf Anforderung mithilfe von Funktionen zur dynamischen Speicherzuweisung zugewiesen und freigegeben.
[bearbeiten] Bindung
Bindung bezieht sich auf die Fähigkeit eines Bezeichners (Variable oder Funktion), in anderen Gültigkeitsbereichen referenziert zu werden. Wenn eine Variable oder Funktion mit demselben Bezeichner in mehreren Gültigkeitsbereichen deklariert wird, aber nicht von allen referenziert werden kann, werden mehrere Instanzen der Variable generiert. Die folgenden Bindungen werden erkannt:
- keine Bindung. Die Variable oder Funktion kann nur aus dem Gültigkeitsbereich referenziert werden, in dem sie sich befindet (Blockebene). Alle Variablen auf Blockebene, die nicht als
externdeklariert sind, haben diese Bindung, ebenso wie alle Funktionsparameter und alle Bezeichner, die keine Funktionen oder Variablen sind.
- keine Bindung. Die Variable oder Funktion kann nur aus dem Gültigkeitsbereich referenziert werden, in dem sie sich befindet (Blockebene). Alle Variablen auf Blockebene, die nicht als
- interne Bindung. Die Variable oder Funktion kann aus allen Gültigkeitsbereichen in der aktuellen Übersetzungseinheit referenziert werden. Alle Variablen auf Dateiebene, die als
staticoderconstexpr(seit C23) deklariert sind, haben diese Bindung, und alle Funktionen auf Dateiebene, die alsstaticdeklariert sind (statische Funktionsdeklarationen sind nur auf Dateiebene erlaubt).
- interne Bindung. Die Variable oder Funktion kann aus allen Gültigkeitsbereichen in der aktuellen Übersetzungseinheit referenziert werden. Alle Variablen auf Dateiebene, die als
- externe Bindung. Die Variable oder Funktion kann aus jeder anderen Übersetzungseinheit im gesamten Programm referenziert werden. Alle Variablen auf Dateiebene, die nicht als
staticoderconstexpr(seit C23) deklariert sind, haben diese Bindung, alle Funktionsdeklarationen auf Dateiebene, die nicht alsstaticdeklariert sind, alle Funktionsdeklarationen auf Blockebene und zusätzlich alle Variablen oder Funktionen, die alsexterndeklariert sind, haben diese Bindung, es sei denn, eine vorherige Deklaration mit interner Bindung ist an dieser Stelle sichtbar.
- externe Bindung. Die Variable oder Funktion kann aus jeder anderen Übersetzungseinheit im gesamten Programm referenziert werden. Alle Variablen auf Dateiebene, die nicht als
Wenn derselbe Bezeichner sowohl mit interner als auch mit externer Bindung in derselben Übersetzungseinheit vorkommt, ist das Verhalten undefiniert. Dies ist möglich, wenn tentative Definitionen verwendet werden.
[bearbeiten] Bindung und Bibliotheken
| Dieser Abschnitt ist unvollständig Grund: Sollte dies ein eigener Haupteintrag unter c/language/Miscellaneous sein? |
Deklarationen mit externer Bindung werden üblicherweise in Header-Dateien verfügbar gemacht, damit alle Übersetzungseinheiten, die die Datei #include-en, denselben Bezeichner referenzieren können, der woanders definiert ist.
Jede Deklaration mit interner Bindung, die in einer Header-Datei vorkommt, führt zu einem separaten und eigenständigen Objekt in jeder Übersetzungseinheit, die diese Datei einschließt.
|
Bibliotheksinterface, Header-Datei "flib.h" #ifndef FLIB_H #define FLIB_H void f(void); // function declaration with external linkage extern int state; // variable declaration with external linkage static const int size = 5; // definition of a read-only variable with internal linkage enum { MAX = 10 }; // constant definition inline int sum (int a, int b) { return a + b; } // inline function definition #endif // FLIB_H Bibliotheksimplementierung, Quelldatei "flib.c" #include "flib.h" static void local_f(int s) {} // definition with internal linkage (only used in this file) static int local_state; // definition with internal linkage (only used in this file) int state; // definition with external linkage (used by main.c) void f(void) { local_f(state); } // definition with external linkage (used by main.c) Anwendungscode, Quelldatei "main.c" #include "flib.h" int main(void) { int x[MAX] = {size}; // uses the constant and the read-only variable state = 7; // modifies state in flib.c f(); // calls f() in flib.c } |
[bearbeiten] Schlüsselwörter
auto, register, static, extern, _Thread_local thread_local
[bearbeiten] Anmerkungen
|
Das Schlüsselwort _Thread_local wird normalerweise über das Makro thread_local verwendet, das in der Header-Datei <threads.h> definiert ist. |
(bis C23) |
Die Spezifizierer typedef und constexpr(seit C23) sind formell als Speicherklassenspezifizierer in der C-Sprachgrammatik aufgeführt, spezifizieren aber keine Speicherung.
|
Der Spezifizierer auto wird auch für die Typinferenz verwendet. |
(seit C23) |
Namen auf Dateiebene, die const und nicht extern sind, haben in C externe Bindung (als Standard für alle Deklarationen auf Dateiebene), in C++ jedoch interne Bindung.
[bearbeiten] Beispiel
#include <stdio.h> #include <stdlib.h> // static storage duration int A; int main(void) { printf("&A = %p\n", (void*)&A); // automatic storage duration int A = 1; // hides global A printf("&A = %p\n", (void*)&A); // allocated storage duration int* ptr_1 = malloc(sizeof(int)); // start allocated storage duration printf("address of int in allocated memory = %p\n", (void*)ptr_1); free(ptr_1); // stop allocated storage duration }
Mögliche Ausgabe
&A = 0x600ae4 &A = 0x7ffefb064f5c address of int in allocated memory = 0x1f28c30
[bearbeiten] Referenzen
- C23-Standard (ISO/IEC 9899:2024)
- 6.2.2 Bindungen von Bezeichnern (S. 35-36)
- 6.2.4 Speicherdauern von Objekten (S. 36-37)
- 6.7.1 Speicherklassenspezifizierer (S. 97-100)
- C17-Standard (ISO/IEC 9899:2018)
- 6.2.2 Bindungen von Bezeichnern (S. 29-30)
- 6.2.4 Speicherdauern von Objekten (S. 30)
- 6.7.1 Speicherklassenspezifizierer (S. 79)
- C11-Standard (ISO/IEC 9899:2011)
- 6.2.2 Bindungen von Bezeichnern (S. 36-37)
- 6.2.4 Speicherdauern von Objekten (S. 38-39)
- 6.7.1 Speicherklassenspezifizierer (S. 109-110)
- C99-Standard (ISO/IEC 9899:1999)
- 6.2.2 Bindungen von Bezeichnern (S. 30-31)
- 6.2.4 Speicherdauern von Objekten (S. 32)
- 6.7.1 Speicherklassenspezifizierer (S. 98-99)
- C89/C90-Standard (ISO/IEC 9899:1990)
- 3.1.2.2 Bindungen von Bezeichnern
- 3.1.2.4 Speicherdauern von Objekten
- 3.5.1 Speicherklassenspezifizierer
[bearbeiten] Siehe auch
| C++ Dokumentation für Speicherklassenspezifizierer
|