Typqualifizierer
Typqualifizierer verleihen einem Bezeichner eine von zwei Eigenschaften. Der Typqualifizierer const
deklariert ein Objekt als nicht änderbar. Der Typqualifizierer volatile
deklariert ein Element, bei dem eine Wertänderung von außerhalb des Programms, in dem es vorhanden ist, zulässig ist (z. B. durch einen gleichzeitig ausgeführten Thread).
Die Typqualifizierer const
, restrict
und volatile
können pro Deklaration nur einmal verwendet werden. Typqualifizierer lassen sich mit beliebigen Typspezifizierern verwenden, dürfen aber in einer Deklaration mit mehreren Elementen nicht hinter dem ersten Komma stehen. Beispielsweise sind die folgenden Deklarationen zulässig:
typedef volatile int VI;
const int ci;
Die folgenden Deklarationen sind nicht zulässig:
typedef int *i, volatile *vi;
float f, const cf;
Typqualifizierer sind nur wichtig, wenn auf Bezeichner als L-Werte in Ausdrücken zugegriffen wird. Weitere Informationen über L-Werte und Ausdrücke finden Sie unter L-Wert- und R-Wert-Ausdrücke.
Syntax
type-qualifier
:
const
restrict
volatile
const
und volatile
Folgende const
- und volatile
-Deklarationen sind zulässig:
int const *p_ci; // Pointer to constant int
int const (*p_ci); // Pointer to constant int
int *const cp_i; // Constant pointer to int
int (*const cp_i); // Constant pointer to int
int volatile vint; // Volatile integer
Wenn die Spezifikation eines Arraytyps Typqualifizierer enthält, wird das Element qualifiziert, nicht der Arraytyp. Enthält die Spezifikation des Funktionstyps Qualifizierer, ist das Verhalten undefiniert. volatile
und const
wirken sich nicht den Wertebereich oder die arithmetischen Eigenschaften des Objekts aus.
Das
const
-Schlüsselwort kann verwendet werden, um jeden grundlegenden oder aggregierten Typ, einen Zeiger auf ein Objekt beliebigen Typs odertypedef
zu ändern. Wenn ein Element nur mit demconst
-Typqualifizierer deklariert ist, lautet der Typ const int. Eineconst
-Variable kann initialisiert oder in einen schreibgeschützten Speicherbereich eingefügt werden. Dasconst
-Schlüsselwort ist gut geeignet, um Zeiger aufconst
zu deklarieren, da die Funktion den Zeiger keinesfalls ändern darf.Der Compiler nimmt an, dass im Programm zu jedem Zeitpunkt der Zugriff auf eine
volatile
-Variable erfolgen kann, und zwar durch einen unbekannten Prozess, der den Wert verwendet oder ändert. Der Code für jede Zuordnung oder für jeden Verweis einervolatile
-Variable muss unabhängig von den in der Befehlszeile angegebenen Optimierungen generiert werden, auch wenn er augenscheinlich keine Auswirkung hat.
Bei alleiniger Verwendung von volatile
wird int
angenommen. Der Typspezifizierer volatile
kann verwendet werden, um zuverlässigen Zugriff auf spezielle Speicheradressen zu ermöglichen. Verwenden Sie volatile
mit Datenobjekten, bei denen der Zugriff oder eine Änderung durch Signalhandler, durch gleichzeitig ausgeführte Programme oder durch spezielle Hardware (wie z. B. im Speicher abgebildete E/A-Steuerungsregister) erfolgen kann. Sie können eine Variable für ihre Verwendungszeit als volatile
deklarieren oder einen einzelnen Verweis in volatile
umwandeln.
- Ein Element kann sowohl
const
als auchvolatile
sein. Dann ist eine Änderung des Elements durch das eigene Programm nicht zulässig, aber eine Änderung durch einen asynchronen Prozess ist möglich.
restrict
Der in C99 eingeführte und im Modus /std:c11
oder /std:c17
verfügbare Typqualifizierer restrict
kann auf Zeigerdeklarationen angewendet werden. Er qualifiziert den Zeiger, nicht das Element, auf das dieser zeigt.
restrict
ist ein Optimierungshinweis an den Compiler, dass kein weiterer Zeiger im aktuellen Bereich auf dieselbe Arbeitsspeicheradresse verweist. Das bedeutet, dass während der Lebensdauer des Zeigers nur der Zeiger oder ein davon abgeleiteter Wert (z. B. Zeiger + 1) für den Zugriff auf das Objekt verwendet wird. Auf diese Weise kann der Compiler einen besser optimierten Code erzeugen. C++ weist einen ähnlichen Mechanismus auf: __restrict
.
Denken Sie daran, dass restrict
ein Vertrag zwischen Ihnen und dem Compiler ist. Wenn Sie für einen mit restrict
gekennzeichneten Zeiger einen Alias verwenden, ist das Ergebnis nicht definiert.
Im Folgenden sehen Sie ein Beispiel, das restrict
verwendet:
void test(int* restrict first, int* restrict second, int* val)
{
*first += *val;
*second += *val;
}
int main()
{
int i = 1, j = 2, k = 3;
test(&i, &j, &k);
return 0;
}
// Marking union members restrict tells the compiler that
// only z.x or z.y will be accessed in any scope, which allows
// the compiler to optimize access to the members.
union z
{
int* restrict x;
double* restrict y;
};
Siehe auch
/std
(Standardversion für die Sprache festlegen)
Deklarationen und Typen