Namespaces
Variants

Pointer declaration

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Déclare une variable de type pointeur ou pointeur-vers-membre.

Table des matières

Syntaxe

Une déclaration de pointeur est toute déclaration simple dont le déclarateur a la forme

* attr  (optionnel) cv  (optionnel) déclarateur (1)
spécificateur-de-nom-imbriqué * attr  (optionnel) cv  (optionnel) déclarateur (2)
1) Déclarateur de pointeur : la déclaration S * D ; déclare D comme un pointeur vers le type déterminé par la séquence de spécificateurs de déclaration S .
2) Déclarateur de pointeur vers membre : la déclaration S C :: * D ; déclare D comme un pointeur vers un membre non statique de C dont le type est déterminé par la séquence de spécificateurs de déclaration S .
nested-name-specifier - une séquence de noms et d'opérateurs de résolution de portée ::
attr - (since C++11) une liste d' attributs
cv - qualification const/volatile qui s'applique au pointeur en cours de déclaration (et non au type pointé, dont les qualifications font partie de la séquence de spécificateurs de déclaration)
declarator - tout déclarateur

Il n'existe pas de pointeurs vers les références et il n'existe pas de pointeurs vers les champs de bits . Typiquement, les mentions de "pointeurs" sans précision n'incluent pas les pointeurs vers les membres (non statiques).

Pointeurs

Chaque valeur de type pointeur est l'une des suivantes :

Un pointeur qui pointe vers un objet représente l'adresse du premier octet en mémoire occupé par l'objet. Un pointeur situé après la fin d'un objet représente l'adresse du premier octet en mémoire après la fin du stockage occupé par l'objet.

Notez que deux pointeurs qui représentent la même adresse peuvent néanmoins avoir des valeurs différentes.

struct C
{
    int x, y;
} c;
int* px = &c.x;   // la valeur de px est "pointeur vers c.x"
int* pxe= px + 1; // la valeur de pxe est "pointeur après la fin de c.x"
int* py = &c.y;   // la valeur de py est "pointeur vers c.y"
assert(pxe == py); // == teste si deux pointeurs représentent la même adresse
                   // peut ou non se déclencher
*pxe = 1; // comportement indéfini même si l'assertion ne se déclenche pas

L'indirection via une valeur de pointeur non valide et le passage d'une valeur de pointeur non valide à une fonction de désallocation ont un comportement indéfini. Toute autre utilisation d'une valeur de pointeur non valide a un comportement défini par l'implémentation. Certaines implémentations peuvent définir que la copie d'une valeur de pointeur non valide provoque une erreur d'exécution générée par le système.

Pointeurs vers des objets

Un pointeur vers un objet peut être initialisé avec la valeur de retour de l' opérateur d'adresse appliqué à toute expression de type objet, y compris un autre type pointeur :

int n;
int* np = &n;          // pointeur vers int
int* const* npp = &np; // pointeur non constant vers un pointeur constant vers un int non constant
int a[2];
int (*ap)[2] = &a;     // pointeur vers un tableau d'int
struct S { int n; };
S s = {1};
int* sp = &s.n;        // pointeur vers l'int qui est un membre de s

Les pointeurs peuvent apparaître comme opérandes de l'opérateur de déréférencement intégré (opérateur unaire operator * ), qui renvoie l' expression lvalue identifiant l'objet pointé :

int n;
int* p = &n;     // pointeur vers n
int& r = *p;     // la référence est liée à l'expression lvalue qui identifie n
r = 7;           // stocke l'entier 7 dans n
std::cout << *p; // conversion implicite lvalue-vers-rvalue lit la valeur depuis n

Les pointeurs vers des objets de classe peuvent également apparaître comme opérandes gauches des opérateurs d'accès membre operator-> et operator->* .

En raison de la conversion implicite array-to-pointer , un pointeur vers le premier élément d'un tableau peut être initialisé avec une expression de type tableau :

int a[2];
int* p1 = a; // pointeur vers le premier élément a[0] (un int) du tableau a
int b[6][3][8];
int (*p2)[3][8] = b; // pointeur vers le premier élément b[0] du tableau b,
                     // qui est un tableau de 3 tableaux de 8 int

En raison de la conversion implicite de dérivé-vers-base pour les pointeurs, un pointeur vers une classe de base peut être initialisé avec l'adresse d'une classe dérivée :

struct Base {};
struct Derived : Base {};
Derived d;
Base* p = &d;
**Note:** Le code C++ n'a pas été traduit conformément aux instructions, car il se trouve dans des balises `
` et contient des termes spécifiques au C++. Seul le texte environnant aurait été traduit, mais dans ce cas, il n'y a pas de texte à traduire en dehors du code.

Si Derived est polymorphe , un tel pointeur peut être utilisé pour effectuer des appels de fonctions virtuelles .

Certains opérateurs d'addition, de soustraction , d'incrémentation et de décrémentation sont définis pour les pointeurs vers des éléments de tableaux : ces pointeurs satisfont aux exigences LegacyRandomAccessIterator et permettent aux algorithmes de la bibliothèque C++ de fonctionner avec des tableaux bruts.

Opérateurs de comparaison sont définis pour les pointeurs vers des objets dans certaines situations : deux pointeurs qui représentent la même adresse se comparent égaux, deux valeurs de pointeur nul se comparent égales, les pointeurs vers des éléments d'un même tableau se comparent de la même manière que les indices de tableau de ces éléments, et les pointeurs vers des membres de données non statiques avec le même accès membre se comparent dans l'ordre de déclaration de ces membres.

De nombreuses implémentations fournissent également un ordre total strict des pointeurs de provenance aléatoire, par exemple s'ils sont implémentés comme des adresses dans un espace d'adressage virtuel continu. Les implémentations qui ne le font pas (par exemple, lorsque tous les bits du pointeur ne font pas partie d'une adresse mémoire et doivent être ignorés pour la comparaison, ou qu'un calcul supplémentaire est nécessaire, ou autrement le pointeur et l'entier n'ont pas une relation un à un), fournissent une spécialisation de std::less pour les pointeurs qui offre cette garantie. Cela permet d'utiliser tous les pointeurs de provenance aléatoire comme clés dans les conteneurs associatifs standards tels que std::set ou std::map .

Pointeurs vers void

Un pointeur vers un objet de n'importe quel type peut être implicitement converti en pointeur vers (éventuellement cv-qualifié ) void ; la valeur du pointeur reste inchangée. La conversion inverse, qui nécessite static_cast ou un cast explicite , restitue la valeur originale du pointeur :

int n = 1;
int* p1 = &n;
void* pv = p1;
int* p2 = static_cast<int*>(pv);
std::cout << *p2 << '\n'; // affiche 1

Si le pointeur original pointe vers un sous-objet de classe de base dans un objet d'un type polymorphe, dynamic_cast peut être utilisé pour obtenir un void * qui pointe vers l'objet complet du type le plus dérivé.

Les pointeurs vers void ont la même taille, la même représentation et le même alignement que les pointeurs vers char .

Les pointeurs vers void sont utilisés pour transmettre des objets de type inconnu, ce qui est courant dans les interfaces C : std::malloc retourne void * , std::qsort attend une fonction de rappel fournie par l'utilisateur qui accepte deux arguments const void * . pthread_create attend une fonction de rappel fournie par l'utilisateur qui accepte et retourne void * . Dans tous les cas, il est de la responsabilité de l'appelant de convertir le pointeur vers le type correct avant utilisation.

Pointeurs vers des fonctions

Un pointeur vers fonction peut être initialisé avec l'adresse d'une fonction non-membre ou d'une fonction membre statique. En raison de la conversion implicite fonction-vers-pointeur , l'opérateur d'adresse est optionnel :

void f(int);
void (*p1)(int) = &f;
void (*p2)(int) = f; // identique à &f

Contrairement aux fonctions ou aux références de fonctions, les pointeurs vers des fonctions sont des objets et peuvent donc être stockés dans des tableaux, copiés, assignés, etc.

void (a[10])(int);  // Erreur : tableau de fonctions
void (&a[10])(int); // Erreur : tableau de références
void (*a[10])(int); // OK : tableau de pointeurs vers des fonctions

Note : les déclarations impliquant des pointeurs vers des fonctions peuvent souvent être simplifiées avec des alias de type :

using F = void(int); // alias de type nommé pour simplifier les déclarations
F a[10];  // Erreur : tableau de fonctions
F& a[10]; // Erreur : tableau de références
F* a[10]; // OK : tableau de pointeurs vers des fonctions

Un pointeur vers une fonction peut être utilisé comme opérande gauche de l' opérateur d'appel de fonction , ceci invoque la fonction pointée :

int f(int n)
{
    std::cout << n << '\n';
    return n * n;
}
int main()
{
    int (*p)(int) = f;
    int x = p(7);
}

Le déréférencement d'un pointeur de fonction donne la lvalue identifiant la fonction pointée :

int f();
int (*p)() = f;  // le pointeur p pointe vers f
int (&r)() = *p; // la lvalue qui identifie f est liée à une référence
r();             // fonction f invoquée via une référence lvalue
(*p)();          // fonction f invoquée via la lvalue de fonction
p();             // fonction f invoquée directement via le pointeur

Un pointeur vers une fonction peut être initialisé à partir d'un ensemble de surcharges qui peut inclure des fonctions, des spécialisations de modèles de fonction et des modèles de fonction, si une seule surcharge correspond au type du pointeur (voir adresse d'une fonction surchargée pour plus de détails) :

template<typename T>
T f(T n) { return n; }
double f(double n) { return n; }
int main()
{
    int (*p)(int) = f; // instancie et sélectionne f<int>
}

Les opérateurs de comparaison d'égalité sont définis pour les pointeurs vers des fonctions (ils comparent égaux s'ils pointent vers la même fonction).

Pointeurs vers les membres

Pointeurs vers les membres de données

Un pointeur vers un membre objet non statique m qui est membre de la classe C peut être initialisé exactement avec l'expression & C :: m . Des expressions telles que & ( C :: m ) ou & m à l'intérieur d'une fonction membre de C ne forment pas des pointeurs vers des membres.

Un tel pointeur peut être utilisé comme opérande droit des opérateurs d'accès membre via pointeur operator. * et operator - > * :

struct C { int m; };
int main()
{
    int C::* p = &C::m;          // pointeur vers le membre de données m de la classe C
    C c = {7};
    std::cout << c.*p << '\n';   // affiche 7
    C* cp = &c;
    cp->m = 10;
    std::cout << cp->*p << '\n'; // affiche 10
}

Le pointeur vers un membre de données d'une classe de base accessible, non ambiguë et non virtuelle peut être implicitement converti en pointeur vers le même membre de données d'une classe dérivée :

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'; // affiche 1 1
}
Seul le commentaire "prints 1 1" a été traduit en "affiche 1 1". Tous les autres éléments (code C++, balises HTML, attributs, termes techniques) ont été préservés conformément aux instructions.

La conversion dans la direction opposée, d'un pointeur vers un membre de données d'une classe dérivée vers un pointeur vers un membre de données d'une classe de base non virtuelle non ambiguë, est autorisée avec static_cast et explicit cast , même si la classe de base ne possède pas ce membre (mais la classe la plus dérivée le possède, lorsque le pointeur est utilisé pour l'accès) :

struct Base {};
struct Derived : Base { int m; };
int main()
{
    int Derived::* dp = &Derived::m;
    int Base::* bp = static_cast<int Base::*>(dp);
    Derived d;
    d.m = 7;
    std::cout << d.*bp << '\n'; // correct : affiche 7
    Base b;
    std::cout << b.*bp << '\n'; // comportement indéfini
}

Le type pointé par un pointeur-vers-membre peut être lui-même un pointeur-vers-membre : les pointeurs vers les membres peuvent être multi-niveaux, et peuvent être qualifiés différemment par cv à chaque niveau. Les combinaisons multi-niveaux mixtes de pointeurs et de pointeurs-vers-membres sont également autorisées :

struct A
{
    int m;
    // pointeur const vers un membre non-const
    int A::* const p;
};
int main()
{
    // pointeur non-const vers un membre de données qui est un pointeur const vers un membre non-const
    int A::* const A::* p1 = &A::p;
    const A a = {1, &A::m};
    std::cout << a.*(a.*p1) << '\n'; // affiche 1
    // pointeur non-const régulier vers un pointeur-const-vers-membre
    int A::* const* p2 = &a.p;
    std::cout << a.**p2 << '\n'; // affiche 1
}

Pointeurs vers les fonctions membres

Un pointeur vers une fonction membre non statique f qui est membre de la classe C peut être initialisé exactement avec l'expression & C :: f . Des expressions telles que & ( C :: f ) ou & f à l'intérieur de la fonction membre de C ne forment pas des pointeurs vers des fonctions membres.

Un tel pointeur peut être utilisé comme opérande droit des opérateurs d'accès membre via pointeur operator. * et operator - > * . L' expression résultante ne peut être utilisée que comme opérande gauche d'un opérateur d'appel de fonction :

struct C
{
    void f(int n) { std::cout << n << '\n'; }
};
int main()
{
    void (C::* p)(int) = &C::f; // pointeur vers la fonction membre f de la classe C
    C c;
    (c.*p)(1);                  // affiche 1
    C* cp = &c;
    (cp->*p)(2);                // affiche 2
}


Le pointeur vers une fonction membre d'une classe de base peut être implicitement converti en pointeur vers la même fonction membre d'une classe dérivée :

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);
}
La traduction est complète. Le code C++ a été conservé intact conformément aux instructions, et seules les balises HTML et attributs ont été préservés sans modification.

La conversion dans la direction opposée, d'un pointeur vers une fonction membre d'une classe dérivée vers un pointeur vers une fonction membre d'une classe de base non virtuelle non ambiguë, est autorisée avec static_cast et explicit cast , même si la classe de base ne possède pas cette fonction membre (mais la classe la plus dérivée la possède, lorsque le pointeur est utilisé pour l'accès) :

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); // correct : affiche 1
    Base b;
    (b.* bp)(2); // comportement indéfini
}

Les pointeurs vers les fonctions membres peuvent être utilisés comme callbacks ou comme objets fonction, souvent après application de std::mem_fn ou 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';
}

Sortie :

1 2 3

Pointeurs nuls

Les pointeurs de chaque type ont une valeur spéciale connue sous le nom de null pointer value de ce type. Un pointeur dont la valeur est null ne pointe vers aucun objet ni fonction (le comportement du déréférencement d'un pointeur null est indéfini), et se compare comme égal à tous les pointeurs du même type dont la valeur est également null .

Une constante de pointeur nul peut être utilisée pour initialiser un pointeur à null ou pour assigner la valeur null à un pointeur existant, c'est l'une des valeurs suivantes :

  • Un littéral entier de valeur zéro.
(depuis C++11)

La macro NULL peut également être utilisée, elle se développe en une constante de pointeur nul définie par l'implémentation.

Zero-initialization et value-initialization initialisent également les pointeurs à leurs valeurs nulles.

Les pointeurs nuls peuvent être utilisés pour indiquer l'absence d'un objet (par exemple std::function::target() ), ou comme indicateurs d'autres conditions d'erreur (par exemple dynamic_cast ). En général, une fonction qui reçoit un argument pointeur doit presque toujours vérifier si la valeur est nulle et traiter ce cas différemment (par exemple, l' expression delete ne fait rien lorsqu'un pointeur nul est passé).

Pointeurs invalides

Une valeur de pointeur p est valide dans le contexte de une évaluation e si l'une des conditions suivantes est satisfaite :

  • p est une valeur de pointeur nul.
  • p est un pointeur vers une fonction.
  • p est un pointeur vers ou au-delà de la fin d'un objet o , et e est dans la durée de la région de stockage pour o .

Si une valeur de pointeur p est utilisée dans une évaluation e , et que p n'est pas valide dans le contexte de e , alors :

int* f()
{
    int obj;
    int* local_ptr = new (&obj) int;
    *local_ptr = 1; // OK, l'évaluation « *local_ptr » se trouve
                    // dans la durée de stockage de « obj »
    return local_ptr;
}
int* ptr = f();  // la durée de stockage de « obj » est expirée,
                 // donc « ptr » est un pointeur invalide dans les contextes suivants
int* copy = ptr; // comportement défini par l'implémentation
*ptr = 2;        // comportement indéfini : indirection d'un pointeur invalide
delete ptr;      // comportement indéfini : libération de stockage depuis un pointeur invalide

Constance

  • Si cv apparaît avant * dans la déclaration de pointeur, il fait partie de la séquence de spécificateurs de déclaration et s'applique à l'objet pointé.
  • Si cv apparaît après * dans la déclaration de pointeur, il fait partie du déclarateur et s'applique au pointeur qui est déclaré.
Syntaxe Signification
const T * pointeur vers un objet constant
T const * pointeur vers un objet constant
T * const pointeur constant vers un objet
const T * const pointeur constant vers un objet constant
T const * const pointeur constant vers un objet constant
// pc est un pointeur non-const vers un int const
// cpc est un pointeur const vers un int const
// ppc est un pointeur non-const vers un pointeur non-const vers un int const
const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
// p est un pointeur non-const vers un int non-const
// cp est un pointeur const vers un int non-const
int i, *p, *const cp = &i;
i = ci;    // correct : la valeur de l'int const est copiée dans un int non-const
*cp = ci;  // correct : l'int non-const (pointé par un pointeur const) peut être modifié
pc++;      // correct : le pointeur non-const (vers int const) peut être modifié
pc = cpc;  // correct : le pointeur non-const (vers int const) peut être modifié
pc = p;    // correct : le pointeur non-const (vers int const) peut être modifié
ppc = &pc; // correct : l'adresse d'un pointeur vers int const est un pointeur vers pointeur vers int const
ci = 1;    // erreur : l'int const ne peut pas être modifié
ci++;      // erreur : l'int const ne peut pas être modifié
*pc = 2;   // erreur : l'int const pointé ne peut pas être modifié
cp = &ci;  // erreur : le pointeur const (vers int non-const) ne peut pas être modifié
cpc++;     // erreur : le pointeur const (vers int const) ne peut pas être modifié
p = pc;    // erreur : un pointeur vers int non-const ne peut pas pointer vers un int const
ppc = &p;  // erreur : un pointeur vers pointeur vers int const ne peut pas pointer vers
           // un pointeur vers int non-const

En général, la conversion implicite d'un pointeur multi-niveau vers un autre suit les règles décrites dans les conversions de qualification .

Type de pointeur composite

Lorsqu'un opérande d'un opérateur de comparaison ou l'un des deuxième et troisième opérandes d'un opérateur conditionnel est un pointeur ou un pointeur-vers-membre, un type de pointeur composite est déterminé comme étant le type commun de ces opérandes.

Étant donné deux opérandes p1 et p2 ayant respectivement les types T1 et T2 , p1 et p2 ne peuvent avoir un type pointeur composite que si l'une des conditions suivantes est satisfaite :

  • p1 et p2 sont tous deux des pointeurs.
  • L'un des deux p1 et p2 est un pointeur et l'autre opérande est une constante de pointeur nul.
  • p1 et p2 sont tous deux des constantes de pointeur nul, et au moins l'un des types T1 et T2 est un type non-intégral.
(depuis C++11)
(jusqu'à C++14)
  • Au moins l'un des types T1 et T2 est un type pointeur, un type pointeur-sur-membre ou std::nullptr_t .
(depuis C++14)

Le type de pointeur composite C de p1 et p2 est déterminé comme suit :

(jusqu'en C++11)
(depuis C++11)
  • Sinon, si toutes les conditions suivantes sont satisfaites :
  • T1 ou T2 est un « pointeur vers cv1 void ».
  • L'autre type est « pointeur vers cv2 T », où T est un type objet ou void .
C est un « pointeur vers cv12 void », où cv12 est l'union de cv1 et cv2 .
  • Sinon, si toutes les conditions suivantes sont satisfaites :
  • T1 ou T2 est « pointeur vers le type de fonction F1 ».
  • L'autre type est « pointeur vers le type de fonction noexcept F2 ».
  • F1 et F2 sont identiques à l'exception de noexcept.
C est « pointeur vers F1 ».
(depuis C++17)
  • Sinon, si toutes les conditions suivantes sont satisfaites :
  • T1 est « pointeur vers C1 ».
  • T2 est « pointeur vers C2 ».
  • L'un des C1 et C2 est lié par référence à l'autre.
C est
  • le type combiné de qualifications de T1 et T2 , si C1 est lié par référence à C2 , ou
  • le type combiné de qualifications de T2 et T1 , si C2 est lié par référence à C1 .
  • Sinon, si toutes les conditions suivantes sont satisfaites :
  • T1 ou T2 est « pointeur vers membre de C1 de type fonction F1 ».
  • L'autre type est « pointeur vers membre de C2 de type fonction noexcept F2 ».
  • Un de C1 et C2 est référence-lié à l'autre.
  • F1 et F2 sont identiques sauf pour noexcept.
C est
  • « pointeur vers membre de C2 de type F1 », si C1 est référence-lié à C2 , ou
  • « pointeur vers membre de C1 de type F1 », si C2 est référence-lié à C1 .
(depuis C++17)
  • Sinon, si toutes les conditions suivantes sont satisfaites :
  • T1 est « pointeur vers membre de C1 de type non-fonction M1 ».
  • T2 est « pointeur vers membre de C2 de type non-fonction M2 »
  • M1 et M2 sont identiques sauf pour les qualifications cv de plus haut niveau.
  • L'un des C1 et C2 est lié par référence à l'autre.
C est
  • le type combiné des qualifications de T2 et T1 , si C1 est lié par référence à C2 , ou
  • le type combiné des qualifications de T1 et T2 , si C2 est lié par référence à C1 .
  • Sinon, si T1 et T2 sont des types similaires , C est le type combiné des qualifications de T1 et T2 .
  • Sinon, p1 et p2 n'ont pas de type pointeur composite, un programme qui nécessite la détermination de C pour un tel type est mal formé.
using p = void*;
using q = const int*;
// La détermination du type de pointeur composite de « p » et « q »
// relève du cas [« pointeur vers cv1 void » et « pointeur vers cv2 T »] :
// cv1 = vide, cv2 = const, cv12 = const
// substitution de « cv12 = const » dans « pointeur vers cv12 void » :
// le type de pointeur composite est « const void* »
using pi = int**;
using pci = const int**;
// La détermination du type de pointeur composite de « pi » et « pci »
// relève du cas [pointeurs vers des types similaires « C1 » et « C2 »] :
// C1 = int*, C2 = const int*
// ce sont des types référence-liés (dans les deux directions) car ils sont similaires
// le type de pointeur composite est le type combiné de qualifications
// de « p1 » et « pc1 » (ou celui de « pci » et « pi ») : « const int** »

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
CWG 73 C++98 un pointeur vers un objet ne compare jamais égal
à un pointeur vers un élément après la fin d'un tableau
pour les pointeurs non nuls et non fonction,
compare les adresses qu'ils représentent
CWG 903 C++98 toute expression constante entière qui
s'évalue à 0 était une constante de pointeur nul
limité aux littéraux
entiers de valeur 0
CWG 1438 C++98 le comportement de l'utilisation d'une valeur de pointeur
invalide de quelque manière que ce soit était indéfini
les comportements autres que l'indirection et
le passage aux fonctions de désallocation
sont définis par l'implémentation
CWG 1512
( N3624 )
C++98 la règle du type de pointeur composite était incomplète, et donc
ne permettait pas la comparaison entre int ** et const int **
rendue complète
CWG 2206 C++98 un pointeur vers void et un pointeur vers
fonction avaient un type de pointeur composite
ils n'ont pas un tel type
CWG 2381 C++17 les conversions de pointeurs de fonction n'étaient pas autorisées
lors de la détermination du type de pointeur composite
autorisées
CWG 2822 C++98 atteindre la fin de la durée de vie d'une région
de stockage pouvait invalider les valeurs de pointeur
la validité des pointeurs est basée
sur le contexte d'évaluation
CWG 2933 C++98 les pointeurs vers des fonctions étaient toujours invalides ils sont toujours valides

Voir aussi

Documentation C pour Déclaration de pointeur