Zeigerdeklaration
Deklariert eine Variable eines Zeiger- oder Zeiger-auf-Mitglied-Typs.
Inhalt |
[bearbeiten] Syntax
Eine Zeigerdeklaration ist jede einfache Deklaration, deren Deklarator die Form hat
* attr (optional) cv (optional) Deklarator |
(1) | ||||||||
verschachtelter-name-spezifizierer * attr (optional) cv (optional) Deklarator |
(2) | ||||||||
S bestimmten Typ.C vom Typ, der durch die Deklarationsspezifizierersequenz S bestimmt wird.| nested-name-specifier | - | eine Sequenz von Namen und Bereichsauflösungsoperatoren :: |
| attr | - | (seit C++11) eine Liste von Attributen |
| cv | - | const/volatile-Qualifikation, die für den zu deklarierenden Zeiger gilt (nicht für den auf den Typ zeigenden, dessen Qualifikationen Teil der Deklarationsspezifizierersequenz sind) |
| Deklarator | - | jeder Deklarator außer einem Referenzdeklarator (es gibt keine Zeiger auf Referenzen). Es kann ein weiterer Zeiger-Deklarator sein (Zeiger auf Zeiger sind erlaubt) |
Es gibt keine Zeiger auf Referenzen und keine Zeiger auf Bitfelder. Typischerweise schließen Erwähnungen von "Zeigern" ohne weitere Erläuterung keine Zeiger auf (nicht-statische) Mitglieder ein.
[bearbeiten] Zeiger
Jeder Wert eines Zeigertyps ist einer der folgenden:
- ein Zeiger auf ein Objekt oder eine Funktion (in diesem Fall sagt man, der Zeiger zeigt auf das Objekt oder die Funktion), oder
- ein Zeiger hinter das Ende eines Objekts, oder
- der Nullzeigerwert für diesen Typ, oder
- ein ungültiger Zeigerwert.
Ein Zeiger, der auf ein Objekt zeigt, repräsentiert die Adresse des ersten Bytes im Speicher, das vom Objekt belegt wird. Ein Zeiger hinter das Ende eines Objekts repräsentiert die Adresse des ersten Bytes im Speicher nach dem Ende des vom Objekt belegten Speichers.
Beachten Sie, dass zwei Zeiger, die dieselbe Adresse repräsentieren, dennoch unterschiedliche Werte haben können.
struct C { int x, y; } c; int* px = &c.x; // value of px is "pointer to c.x" int* pxe= px + 1; // value of pxe is "pointer past the end of c.x" int* py = &c.y; // value of py is "pointer to c.y" assert(pxe == py); // == tests if two pointers represent the same address // may or may not fire *pxe = 1; // undefined behavior even if the assertion does not fire
Indirektion über einen ungültigen Zeigerwert und Übergabe eines ungültigen Zeigerwerts an eine Freigabefunktion haben undefiniertes Verhalten. Jede andere Verwendung eines ungültigen Zeigerwerts hat implementierungsdefiniertes Verhalten. Einige Implementierungen definieren möglicherweise, dass das Kopieren eines ungültigen Zeigerwerts zu einem systemgenerierten Laufzeitfehler führt.
[bearbeiten] Objektzeiger
Ein Zeiger auf ein Objekt kann mit dem Rückgabewert des Adressoperator initialisiert werden, der auf einen Ausdruck von Objekttyp angewendet wird, einschließlich eines anderen Zeigertyps.
int n; int* np = &n; // pointer to int int* const* npp = &np; // non-const pointer to const pointer to non-const int int a[2]; int (*ap)[2] = &a; // pointer to array of int struct S { int n; }; S s = {1}; int* sp = &s.n; // pointer to the int that is a member of s
Zeiger können Operanden des eingebauten Indirektionsoperators (unäres operator*) sein, der den lvalue-Ausdruck zurückgibt, der das referenzierte Objekt identifiziert.
int n; int* p = &n; // pointer to n int& r = *p; // reference is bound to the lvalue expression that identifies n r = 7; // stores the int 7 in n std::cout << *p; // lvalue-to-rvalue implicit conversion reads the value from n
Zeiger auf Klassenobjekte können auch als linke Operanden der Member-Zugriffsoperatoren operator-> und operator->* auftreten.
Aufgrund der impliziten Konvertierung von Arrays zu Zeigern kann ein Zeiger auf das erste Element eines Arrays mit einem Ausdruck von Arraytyp initialisiert werden.
int a[2]; int* p1 = a; // pointer to the first element a[0] (an int) of the array a int b[6][3][8]; int (*p2)[3][8] = b; // pointer to the first element b[0] of the array b, // which is an array of 3 arrays of 8 ints
Aufgrund der impliziten Konvertierung von Basisklassen zu abgeleiteten Klassen für Zeiger kann ein Zeiger auf eine Basisklasse mit der Adresse einer abgeleiteten Klasse initialisiert werden.
struct Base {}; struct Derived : Base {}; Derived d; Base* p = &d;
Wenn Derived polymorph ist, kann ein solcher Zeiger verwendet werden, um virtuelle Funktionsaufrufe durchzuführen.
Bestimmte Additions-, Subtraktions-, Inkrement- und Dekrementoperatoren sind für Zeiger auf Array-Elemente definiert: solche Zeiger erfüllen die LegacyRandomAccessIterator-Anforderungen und ermöglichen es den C++-Bibliotheks-Algorithmen, mit rohen Arrays zu arbeiten.
Vergleichsoperatoren sind für Zeiger auf Objekte in einigen Situationen definiert: Zwei Zeiger, die dieselbe Adresse repräsentieren, vergleichen sich gleich, zwei Nullzeigerwerte vergleichen sich gleich, Zeiger auf Elemente desselben Arrays vergleichen sich genauso wie die Array-Indizes dieser Elemente, und Zeiger auf nicht-statische Datenmember mit demselben Mitgliederzugriff vergleichen sich in der Reihenfolge der Deklaration dieser Member.
Viele Implementierungen bieten auch eine strikte totale Ordnung von Zeigern beliebigen Ursprungs, z. B. wenn sie als Adressen innerhalb eines kontinuierlichen virtuellen Adressraums implementiert sind. Implementierungen, die dies nicht tun (z. B. wenn nicht alle Bits des Zeigers Teil einer Speicheradresse sind und für den Vergleich ignoriert werden müssen, oder eine zusätzliche Berechnung erforderlich ist oder anderweitig Zeiger und Integer keine 1:1-Beziehung darstellen), bieten eine Spezialisierung von std::less für Zeiger, die diese Garantie hat. Dies ermöglicht die Verwendung aller Zeiger beliebigen Ursprungs als Schlüssel in Standard-Assoziativcontainern wie std::set oder std::map.
[bearbeiten] Zeiger auf void
Ein Zeiger auf ein Objekt beliebigen Typs kann implizit konvertiert werden in einen Zeiger auf einen (möglicherweise cv-qualifizierten) void; der Zeigerwert bleibt unverändert. Die umgekehrte Konvertierung, die eine static_cast oder explizite Umwandlung erfordert, ergibt den ursprünglichen Zeigerwert.
int n = 1; int* p1 = &n; void* pv = p1; int* p2 = static_cast<int*>(pv); std::cout << *p2 << '\n'; // prints 1
Wenn der ursprüngliche Zeiger auf ein Basisklassen-Subobjekt innerhalb eines Objekts eines polymorphen Typs zeigt, kann dynamic_cast verwendet werden, um einen void* zu erhalten, der auf das vollständige Objekt des abgeleitetsten Typs zeigt.
Zeiger auf void haben dieselbe Größe, Darstellung und Ausrichtung wie Zeiger auf char.
Zeiger auf void werden verwendet, um Objekte unbekannten Typs zu übergeben, was in C-Schnittstellen üblich ist: std::malloc gibt void* zurück, std::qsort erwartet eine vom Benutzer bereitgestellte Callback-Funktion, die zwei const void* Argumente akzeptiert. pthread_create erwartet eine vom Benutzer bereitgestellte Callback-Funktion, die void* akzeptiert und zurückgibt. In allen Fällen liegt es in der Verantwortung des Aufrufers, den Zeiger vor der Verwendung in den korrekten Typ umzuwandeln.
[bearbeiten] Funktionszeiger
Ein Zeiger auf eine Funktion kann mit der Adresse einer Nicht-Member-Funktion oder einer statischen Member-Funktion initialisiert werden. Aufgrund der impliziten Konvertierung von Funktionen zu Zeigern ist der Adressoperator optional.
void f(int); void (*p1)(int) = &f; void (*p2)(int) = f; // same as &f
Im Gegensatz zu Funktionen oder Referenzen auf Funktionen sind Funktionszeiger Objekte und können daher in Arrays gespeichert, kopiert, zugewiesen usw. werden.
void (a[10])(int); // Error: array of functions void (&a[10])(int); // Error: array of references void (*a[10])(int); // OK: array of pointers to functions
Hinweis: Deklarationen, die Funktionszeiger beinhalten, können oft durch Typ-Aliase vereinfacht werden.
using F = void(int); // named type alias to simplify declarations F a[10]; // Error: array of functions F& a[10]; // Error: array of references F* a[10]; // OK: array of pointers to functions
Ein Funktionszeiger kann als linker Operand des Funktionsaufrufoperators verwendet werden, dies ruft die referenzierte Funktion auf.
int f(int n) { std::cout << n << '\n'; return n * n; } int main() { int (*p)(int) = f; int x = p(7); }
Dereferenzieren eines Funktionszeigers ergibt den lvalue, der die referenzierte Funktion identifiziert.
int f(); int (*p)() = f; // pointer p is pointing to f int (&r)() = *p; // the lvalue that identifies f is bound to a reference r(); // function f invoked through lvalue reference (*p)(); // function f invoked through the function lvalue p(); // function f invoked directly through the pointer
Ein Funktionszeiger kann aus einem Überladungsset initialisiert werden, das Funktionen, spezialisierte Funktionsvorlagen und Funktionsvorlagen enthalten kann, wenn nur eine Überladung dem Typ des Zeigers entspricht (siehe Adresse einer überladenen Funktion für weitere Details).
template<typename T> T f(T n) { return n; } double f(double n) { return n; } int main() { int (*p)(int) = f; // instantiates and selects f<int> }
Gleichheitsvergleichsoperatoren sind für Funktionszeiger definiert (sie vergleichen sich gleich, wenn sie auf dieselbe Funktion zeigen).
[bearbeiten] Zeiger auf Mitglieder
[bearbeiten] Zeiger auf Datenmember
Ein Zeiger auf ein nicht-statisches Objektmitglied m, das ein Mitglied der Klasse C ist, kann exakt mit dem Ausdruck &C::m initialisiert werden. Ausdrücke wie &(C::m) oder &m innerhalb einer Member-Funktion von C bilden keine Zeiger auf Mitglieder.
Ein solcher Zeiger kann als rechter Operand der Zeiger-auf-Mitglied-Zugriffsoperatoren operator.* und operator->* verwendet werden.
Ein Zeiger auf ein Datenmitglied einer zugänglichen, eindeutigen, nicht-virtuellen Basisklasse kann implizit konvertiert werden in einen Zeiger auf dasselbe Datenmitglied einer abgeleiteten Klasse.
struct Base { int m; }; struct Derived : Base {}; int main() { int Base::* bp = &Base::m; int Derived::* dp = bp; Derived d; d.m = 1; std::cout << d.*dp << ' ' << d.*bp << '\n'; // prints 1 1 }
Eine Konvertierung in die entgegengesetzte Richtung, von einem Zeiger auf ein Datenmitglied einer abgeleiteten Klasse zu einem Zeiger auf ein Datenmitglied einer eindeutigen, nicht-virtuellen Basisklasse, ist mit static_cast und expliziter Umwandlung erlaubt, auch wenn die Basisklasse dieses Mitglied nicht hat (aber die abgeleitetste Klasse hat es, wenn der Zeiger für den Zugriff verwendet wird).
Der auf den Typ zeigende Teil eines Zeigers auf ein Mitglied kann selbst ein Zeiger auf ein Mitglied sein: Zeiger auf Mitglieder können mehrstufig sein und können auf jeder Ebene unterschiedlich cv-qualifiziert sein. Gemischte mehrstufige Kombinationen von Zeigern und Zeigern auf Mitglieder sind ebenfalls erlaubt.
struct A { int m; // const pointer to non-const member int A::* const p; }; int main() { // non-const pointer to data member which is a const pointer to non-const member int A::* const A::* p1 = &A::p; const A a = {1, &A::m}; std::cout << a.*(a.*p1) << '\n'; // prints 1 // regular non-const pointer to a const pointer-to-member int A::* const* p2 = &a.p; std::cout << a.**p2 << '\n'; // prints 1 }
[bearbeiten] Zeiger auf Memberfunktionen
Ein Zeiger auf eine nicht-statische Memberfunktion f, die ein Mitglied der Klasse C ist, kann exakt mit dem Ausdruck &C::f initialisiert werden. Ausdrücke wie &(C::f) oder &f innerhalb einer Member-Funktion von C bilden keine Zeiger auf Memberfunktionen.
Ein solcher Zeiger kann als rechter Operand der Zeiger-auf-Mitglied-Zugriffsoperatoren operator.* und operator->* verwendet werden. Der resultierende Ausdruck kann nur als linker Operand eines Funktionsaufrufoperators verwendet werden.
struct C { void f(int n) { std::cout << n << '\n'; } }; int main() { void (C::* p)(int) = &C::f; // pointer to member function f of class C C c; (c.*p)(1); // prints 1 C* cp = &c; (cp->*p)(2); // prints 2 }
Ein Zeiger auf eine Memberfunktion einer Basisklasse kann implizit konvertiert werden in einen Zeiger auf dieselbe Memberfunktion einer abgeleiteten Klasse.
struct Base { void f(int n) { std::cout << n << '\n'; } }; struct Derived : Base {}; int main() { void (Base::* bp)(int) = &Base::f; void (Derived::* dp)(int) = bp; Derived d; (d.*dp)(1); (d.*bp)(2); }
Eine Konvertierung in die entgegengesetzte Richtung, von einem Zeiger auf eine Memberfunktion einer abgeleiteten Klasse zu einem Zeiger auf eine Memberfunktion einer eindeutigen, nicht-virtuellen Basisklasse, ist mit static_cast und expliziter Umwandlung erlaubt, auch wenn die Basisklasse diese Memberfunktion nicht hat (aber die abgeleitetste Klasse hat sie, wenn der Zeiger für den Zugriff verwendet wird).
struct Base {}; struct Derived : Base { void f(int n) { std::cout << n << '\n'; } }; int main() { void (Derived::* dp)(int) = &Derived::f; void (Base::* bp)(int) = static_cast<void (Base::*)(int)>(dp); Derived d; (d.*bp)(1); // okay: prints 1 Base b; (b.*bp)(2); // undefined behavior }
Zeiger auf Memberfunktionen können als Callbacks oder als Funktions-Objekte verwendet werden, oft nach Anwendung von std::mem_fn oder std::bind.
#include <algorithm> #include <cstddef> #include <functional> #include <iostream> #include <string> int main() { std::vector<std::string> v = {"a", "ab", "abc"}; std::vector<std::size_t> l; transform(v.begin(), v.end(), std::back_inserter(l), std::mem_fn(&std::string::size)); for (std::size_t n : l) std::cout << n << ' '; std::cout << '\n'; }
Ausgabe
1 2 3
[bearbeiten] Nullzeiger
Zeiger jedes Typs haben einen speziellen Wert, der als Nullzeigerwert dieses Typs bekannt ist. Ein Zeiger, dessen Wert null ist, zeigt nicht auf ein Objekt oder eine Funktion (das Verhalten des Dereferenzierens eines Nullzeigers ist undefiniert) und vergleicht sich gleich mit allen Zeigern desselben Typs, deren Wert ebenfalls null ist.
Eine Nullzeigerkonstante kann verwendet werden, um einen Zeiger auf null zu initialisieren oder um den Nullwert einem vorhandenen Zeiger zuzuweisen; sie ist einer der folgenden Werte:
- Ein Ganzzahl-Literal mit dem Wert Null.
|
(seit C++11) |
Das Makro NULL kann ebenfalls verwendet werden, es expandiert zu einer implementierungsdefinierten Nullzeigerkonstante.
Null-Initialisierung und Wert-Initialisierung initialisieren Zeiger ebenfalls mit ihren Nullwerten.
Nullzeiger können verwendet werden, um die Abwesenheit eines Objekts anzuzeigen (z. B. std::function::target()) oder als Indikatoren für andere Fehlerbedingungen (z. B. dynamic_cast). Im Allgemeinen muss eine Funktion, die ein Zeigerargument empfängt, fast immer überprüfen, ob der Wert null ist, und diesen Fall anders behandeln (z. B. bewirkt der delete-Ausdruck nichts, wenn ein Nullzeiger übergeben wird).
[bearbeiten] Ungültige Zeiger
Ein Zeigerwert p ist im Kontext einer Auswertung e gültig, wenn eine der folgenden Bedingungen erfüllt ist:
- p ist ein Nullzeigerwert.
- p ist ein Zeiger auf eine Funktion.
- p ist ein Zeiger auf oder hinter das Ende eines Objekts o, und e liegt innerhalb der Lebensdauer des Speicherbereichs für o.
Wenn ein Zeigerwert p in einer Auswertung e verwendet wird und p im Kontext von e nicht gültig ist, dann:
- Wenn e eine Indirektion oder ein Aufruf einer Freigabefunktion ist, ist das Verhalten undefiniert.
- Andernfalls ist das Verhalten implementierungsdefiniert.
int* f() { int obj; int* local_ptr = new (&obj) int; *local_ptr = 1; // OK, the evaluation “*local_ptr” is // in the storage duration of “obj” return local_ptr; } int* ptr = f(); // the storage duration of “obj” is expired, // therefore “ptr” is an invalid pointer in the following contexts int* copy = ptr; // implementation-defined behavior *ptr = 2; // undefined behavior: indirection of an invalid pointer delete ptr; // undefined behavior: deallocating storage from an invalid pointer
[bearbeiten] Constness
- Wenn cv vor
*in der Zeigerdeklaration erscheint, ist es Teil der Deklarationsspezifizierersequenz und gilt für das referenzierte Objekt. - Wenn cv nach
*in der Zeigerdeklaration erscheint, ist es Teil des Deklarators und gilt für den zu deklarierenden Zeiger.
| Syntax | Bedeutung |
|---|---|
| const T* | Zeiger auf konstantes Objekt |
| T const* | Zeiger auf konstantes Objekt |
| T* const | Konstanter Zeiger auf Objekt |
| const T* const | Konstanter Zeiger auf konstantes Objekt |
| T const* const | Konstanter Zeiger auf konstantes Objekt |
// pc is a non-const pointer to const int // cpc is a const pointer to const int // ppc is a non-const pointer to non-const pointer to const int const int ci = 10, *pc = &ci, *const cpc = pc, **ppc; // p is a non-const pointer to non-const int // cp is a const pointer to non-const int int i, *p, *const cp = &i; i = ci; // okay: value of const int copied into non-const int *cp = ci; // okay: non-const int (pointed-to by const pointer) can be changed pc++; // okay: non-const pointer (to const int) can be changed pc = cpc; // okay: non-const pointer (to const int) can be changed pc = p; // okay: non-const pointer (to const int) can be changed ppc = &pc; // okay: address of pointer to const int is pointer to pointer to const int ci = 1; // error: const int cannot be changed ci++; // error: const int cannot be changed *pc = 2; // error: pointed-to const int cannot be changed cp = &ci; // error: const pointer (to non-const int) cannot be changed cpc++; // error: const pointer (to const int) cannot be changed p = pc; // error: pointer to non-const int cannot point to const int ppc = &p; // error: pointer to pointer to const int cannot point to // pointer to non-const int
Im Allgemeinen folgt die implizite Konvertierung von einem mehrstufigen Zeiger zu einem anderen den Regeln, die unter Qualifikationskonvertierungen beschrieben sind.
[bearbeiten] Zusammengesetzter Zeigertyp
Wenn ein Operand eines Vergleichsoperators oder eines der zweiten und dritten Operanden eines bedingten Operators ein Zeiger oder Zeiger-auf-Mitglied ist, wird ein zusammengesetzter Zeigertyp als gemeinsamer Typ dieser Operanden bestimmt.
Gegeben seien zwei Operanden p1 und p2 mit den Typen T1 bzw. T2. p1 und p2 können nur dann einen zusammengesetzten Zeigertyp haben, wenn eine der folgenden Bedingungen erfüllt ist:
|
(bis C++14) | ||
|
(seit C++14) |
Der zusammengesetzte Zeigertyp C von p1 und p2 wird wie folgt bestimmt:
|
(bis C++11) |
|
(seit C++11) |
- Wenn andernfalls alle folgenden Bedingungen erfüllt sind:
-
T1oderT2ist „Zeiger auf cv1 void“. - Der andere Typ ist „Zeiger auf cv2
T“, wobeiTein Objekttyp oder void ist.
-
-
Cist „Zeiger auf cv12 void“, wobei cv12 die Vereinigung von cv1 und cv2 ist.
|
(seit C++17) |
- Wenn andernfalls alle folgenden Bedingungen erfüllt sind:
-
T1ist „Zeiger aufC1“. -
T2ist „Zeiger aufC2“. - Einer der Typen
C1undC2ist referenzbezogen zum anderen.
-
-
Cist- der qualifikationskombinierte Typ von
T1undT2, wennC1referenzbezogen zuC2ist, oder - der qualifikationskombinierte Typ von
T2undT1, wennC2referenzbezogen zuC1ist.
- der qualifikationskombinierte Typ von
|
(seit C++17) |
- Wenn andernfalls alle folgenden Bedingungen erfüllt sind:
-
T1ist „Zeiger auf Mitglied vonC1vom Nicht-FunktionstypM1“. -
T2ist „Zeiger auf Mitglied vonC2vom Nicht-FunktionstypM2“ -
M1undM2sind gleich, abgesehen von Top-Level-cv-Qualifikationen. - Einer der Typen
C1undC2ist referenzbezogen zum anderen.
-
-
Cist- der qualifikationskombinierte Typ von
T2undT1, wennC1referenzbezogen zuC2ist, oder - der qualifikationskombinierte Typ von
T1undT2, wennC2referenzbezogen zuC1ist.
- der qualifikationskombinierte Typ von
- Wenn andernfalls, wenn
T1undT2ähnliche Typen sind, istCder qualifikationskombinierte Typ vonT1undT2. - Andernfalls haben p1 und p2 keinen zusammengesetzten Zeigertyp; ein Programm, das die Bestimmung eines solchen Typs
Cerfordert, ist ill-formed.
using p = void*; using q = const int*; // The determination of the composite pointer type of “p” and “q” // falls into the [“pointer to cv1 void” and “pointer to cv2 T”] case: // cv1 = empty, cv2 = const, cv12 = const // substitute “cv12 = const” into “pointer to cv12 void”: // the composite pointer type is “const void*” using pi = int**; using pci = const int**; // The determination of the composite pointer type of “pi” and “pci” // falls into the [pointers to similar types “C1” and “C2”] case: // C1 = int*, C2 = const int* // they are reference-related types (in both direction) because they are similar // the composite pointer type is the qualification-combined type // of “p1” and “pc1” (or that of “pci” and “pi”): “const void* const *”
[bearbeiten] Defect reports
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 73 | C++98 | Ein Zeiger auf ein Objekt vergleicht sich nie gleich mit einem Zeiger auf das Ende eines Arrays |
für nicht-null und nicht-Funktionszeiger, vergleiche die von ihnen repräsentierten Adressen |
| CWG 903 | C++98 | jeder Ganzzahl-Konstantausdruck, der zu 0 ausgewertet wird, war eine Nullzeigerkonstante |
beschränkt auf Ganzzahl Literale mit Wert 0 |
| CWG 1438 | C++98 | Das Verhalten bei der Verwendung eines ungültigen Zeiger Wertes in irgendeiner Weise war undefiniert |
Verhalten außer Indirektion und Übergabe an Freigabefunktionen sind implementierungsdefiniert |
| CWG 1512 (N3624) |
C++98 | Die Regel des zusammengesetzten Zeigertyps war unvollständig und damit erlaubte keinen Vergleich zwischen int** und const int** |
vollständig gemacht |
| CWG 2206 | C++98 | Ein Zeiger auf void und ein Zeiger auf eine Funktion hatten einen zusammengesetzten Zeigertyp |
sie haben keinen solchen Typ |
| CWG 2381 | C++17 | Funktionszeiger-Konvertierungen waren nicht erlaubt bei der Bestimmung des zusammengesetzten Zeigertyps |
erlaubt |
| CWG 2822 | C++98 | Erreichen des Endes der Lebensdauer eines Speicherbereichs könnte Zeigerwerte ungültig machen |
Zeigergültigkeit basiert auf dem Auswertungskontext |
| CWG 2933 | C++98 | Funktionszeiger waren immer ungültig | sie sind immer gültig |
[bearbeiten] Siehe auch
| C-Dokumentation für Zeigerdeklaration
|