Storage-class specifiers
Bestimmen Sie die Speicherdauer und Verknüpfung von Objekten und Funktionen:
-
-
auto- automatische Speicherdauer und keine Verknüpfung -
register- automatische Speicherdauer und keine Verknüpfung; Adresse dieser Variable kann nicht genommen werden -
static- statische Speicherdauer und interne Verknüpfung (außer bei Blockgültigkeit) -
extern- statische Speicherdauer und externe Verknüpfung (sofern nicht bereits als intern deklariert)
-
|
(seit C11) |
Inhaltsverzeichnis |
Erklärung
Speicherklassenspezifizierer erscheinen in Deklarationen und Compound-Literal Ausdrücken (seit C23) . Höchstens ein Spezifizierer darf verwendet werden , außer dass _Thread_local (bis C23) thread_local (seit C23) kombiniert werden kann mit static oder extern zur Anpassung der Verknüpfung (seit C11) . Die Speicherklassenspezifizierer bestimmen zwei unabhängige Eigenschaften der von ihnen deklarierten Namen: Speicherdauer und Verknüpfung .
_Alignas
(bis C23)
alignas
(seit C23)
(seit C11)
verwenden, und
register
-Arrays sind nicht in Zeiger konvertierbar.
|
5)
_Thread_local
(bis C23)
thread_local
(seit C23)
kennzeichnet
Thread-Speicherdauer
. Es kann nicht mit Funktionsdeklarationen verwendet werden. Wenn es bei der Deklaration eines Objekts verwendet wird, muss es bei jeder Deklaration desselben Objekts vorhanden sein. Wenn es bei einer Blockbereichsdeklaration verwendet wird, muss es entweder mit
static
oder
extern
kombiniert werden, um die Linkage zu bestimmen.
|
(seit C11) |
Wenn kein Speicherklassenspezifizierer angegeben wird, sind die Standardwerte:
- extern für alle Funktionen
- extern für Objekte im Dateigültigkeitsbereich
- auto für Objekte im Blockgültigkeitsbereich
Für jede Struktur oder Union, die mit einem Speicherklassenspezifizierer deklariert wird, gilt die Speicherdauer (jedoch nicht die Bindung) für ihre Mitglieder, rekursiv.
Funktionsdeklarationen im Blockbereich können extern oder gar keine Spezifizierer verwenden. Funktionsdeklarationen im Dateibereich können extern oder static verwenden.
Funktionsparameter dürfen keine anderen Speicherklassenspezifizierer als register verwenden. Beachten Sie, dass static eine spezielle Bedeutung bei Funktionsparametern vom Array-Typ hat.
Speicherdauer
Jedes Objekt besitzt eine Eigenschaft namens Speicherdauer , die die Lebensdauer des Objekts begrenzt. Es gibt vier Arten von Speicherdauer in C:
-
- automatic Speicherdauer. Der Speicher wird zugewiesen, wenn der Block betreten wird, in dem das Objekt deklariert wurde, und freigegeben, wenn er auf beliebige Weise verlassen wird ( goto , return , Erreichen des Endes). Eine Ausnahme sind VLAs ; ihr Speicher wird bei Ausführung der Deklaration zugewiesen, nicht beim Blockeintritt, und freigegeben, wenn die Deklaration den Gültigkeitsbereich verlässt, nicht wenn der Block verlassen wird (seit C99) . Wenn der Block rekursiv betreten wird, erfolgt für jede Rekursionsebene eine neue Zuweisung. Alle Funktionsparameter und nicht- static Blockbereichsobjekte haben diese Speicherdauer, sowie compound literals die im Blockbereich verwendet werden (bis C23)
- static Speicherdauer. Die Speicherdauer umfasst die gesamte Programmausführung, und der im Objekt gespeicherte Wert wird nur einmal initialisiert, vor der main-Funktion . Alle mit static deklarierten Objekte und alle Objekte mit interner oder externer Verknüpfung die nicht als _Thread_local (bis C23) thread_local (seit C23) deklariert sind (seit C11) haben diese Speicherdauer.
|
(seit C11) |
-
- allocated Speicherdauer. Der Speicher wird bei Bedarf allokiert und freigegeben, unter Verwendung von dynamischen Speicherallokationsfunktionen .
Verknüpfung
Linkage bezieht sich auf die Fähigkeit eines Identifikators (Variable oder Funktion), in anderen Gültigkeitsbereichen referenziert zu werden. Wenn eine Variable oder Funktion mit demselben Identifikator in mehreren Gültigkeitsbereichen deklariert wird, aber nicht von allen referenziert werden kann, dann werden mehrere Instanzen der Variable erzeugt. Die folgenden Linkage-Arten werden unterschieden:
-
-
keine Verknüpfung
. Auf die Variable oder Funktion kann nur aus dem Gültigkeitsbereich heraus zugegriffen werden, in dem sie sich befindet (Blockgültigkeitsbereich). Alle Blockgültigkeitsbereich-Variablen, die nicht als
externdeklariert sind, haben diese Verknüpfung, ebenso alle Funktionsparameter und alle Bezeichner, die keine Funktionen oder Variablen sind.
-
keine Verknüpfung
. Auf die Variable oder Funktion kann nur aus dem Gültigkeitsbereich heraus zugegriffen werden, in dem sie sich befindet (Blockgültigkeitsbereich). Alle Blockgültigkeitsbereich-Variablen, die nicht als
-
-
internal linkage
. Auf die Variable oder Funktion kann von allen Gültigkeitsbereichen in der aktuellen Übersetzungseinheit aus zugegriffen werden. Alle Dateibereichsvariablen, die als
staticoderconstexpr(seit C23) deklariert sind, haben diese Bindung, ebenso wie alle Dateibereichsfunktionen, die alsstaticdeklariert sind (statische Funktionsdeklarationen sind nur im Dateibereich erlaubt).
-
internal linkage
. Auf die Variable oder Funktion kann von allen Gültigkeitsbereichen in der aktuellen Übersetzungseinheit aus zugegriffen werden. Alle Dateibereichsvariablen, die als
-
-
external linkage
. Die Variable oder Funktion kann von allen anderen Übersetzungseinheiten im gesamten Programm referenziert werden. Alle Dateibereichsvariablen, die nicht als
staticoderconstexpr(since C23) deklariert sind, haben diese Bindung, alle Dateibereichsfunktionsdeklarationen, die nicht alsstaticdeklariert sind, alle Blockbereichsfunktionsdeklarationen und zusätzlich alle Variablen oder Funktionen, die alsexterndeklariert sind, haben diese Bindung, sofern keine vorherige Deklaration mit interner Bindung an dieser Stelle sichtbar ist.
-
external linkage
. Die Variable oder Funktion kann von allen anderen Übersetzungseinheiten im gesamten Programm referenziert werden. Alle Dateibereichsvariablen, die nicht als
Wenn derselbe Bezeichner im selben Übersetzungseinheit sowohl mit interner als auch externer Verknüpfung erscheint, ist das Verhalten undefiniert. Dies ist möglich, wenn vorläufige Definitionen verwendet werden.
Verknüpfung und Bibliotheken
|
Dieser Abschnitt ist unvollständig
Grund: Sollte dies ein separater Top-Level-Eintrag in c/language unter Verschiedenes sein? |
Deklarationen mit externer Bindung werden üblicherweise in Header-Dateien bereitgestellt, damit alle Übersetzungseinheiten, die #include die Datei auf dieselben Bezeichner verweisen können, die an anderer Stelle definiert sind.
Jede Deklaration mit interner Verknüpfung, die in einer Header-Datei erscheint, führt zu einem separaten und eigenständigen Objekt in jeder Übersetzungseinheit, die diese Datei einbindet.
Bibliotheksschnittstelle, Header-Datei "flib.h":
#ifndef FLIB_H #define FLIB_H void f(void); // Funktionsdeklaration mit externer Bindung extern int state; // Variablendeklaration mit externer Bindung static const int size = 5; // Definition einer schreibgeschützten Variable mit interner Bindung enum { MAX = 10 }; // Konstantendefinition inline int sum (int a, int b) { return a + b; } // Inline-Funktionsdefinition #endif // FLIB_H
Bibliotheksimplementierung, Quelldatei "flib.c":
#include "flib.h" static void local_f(int s) {} // Definition mit internem Linkage (nur in dieser Datei verwendet) static int local_state; // Definition mit internem Linkage (nur in dieser Datei verwendet) int state; // Definition mit externem Linkage (wird von main.c verwendet) void f(void) { local_f(state); } // Definition mit externem Linkage (wird von main.c verwendet)
Anwendungscode, Quelldatei "main.c":
#include "flib.h" int main(void) { int x[MAX] = {size}; // verwendet die Konstante und die schreibgeschützte Variable state = 7; // modifiziert state in flib.c f(); // ruft f() in flib.c auf }
Schlüsselwörter
auto , register , static , extern , _Thread_local thread_local
Hinweise
|
Das Schlüsselwort _Thread_local wird normalerweise über das praktische Makro thread_local verwendet, das im Header <threads.h> definiert ist. |
(bis C23) |
Die
typedef
und
constexpr
(seit C23)
Spezifizierer sind formal in der C-Sprachgrammatik als Speicherklassen-Spezifizierer aufgeführt, legen jedoch keinen Speicher fest.
|
Der auto-Spezifizierer wird ebenfalls für Typinferenz verwendet. |
(since C23) |
Namen im Dateibereich, die const und nicht extern sind, haben externe Bindung in C (als Standard für alle Deklarationen im Dateibereich), aber interne Bindung in C++.
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
Referenzen
- C23-Standard (ISO/IEC 9899:2024):
-
- 6.2.2 Verknüpfungen von Bezeichnern (S: 35-36)
-
- 6.2.4 Speicherdauern von Objekten (S: 36-37)
-
- 6.7.1 Speicherklassen-Spezifizierer (S: 97-100)
- C17-Standard (ISO/IEC 9899:2018):
-
- 6.2.2 Verknüpfungen von Bezeichnern (S: 29-30)
-
- 6.2.4 Speicherdauer von Objekten (S: 30)
-
- 6.7.1 Speicherklassenspezifizierer (S: 79)
- C11-Standard (ISO/IEC 9899:2011):
-
- 6.2.2 Verknüpfungen 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 Verknüpfungen von Bezeichnern (S: 30-31)
-
- 6.2.4 Speicherdauer von Objekten (S: 32)
-
- 6.7.1 Speicherklassenspezifizierer (S: 98-99)
- C89/C90-Standard (ISO/IEC 9899:1990):
-
- 3.1.2.2 Verknüpfungen von Bezeichnern
-
- 3.1.2.4 Speicherdauern von Objekten
-
- 3.5.1 Speicherklassenspezifizierer
Siehe auch
|
C++ Dokumentation
für
Storage class specifiers
|