78 votes

Est le comportement de la soustraction de deux pointeurs NULL défini

Est la différence de deux non-nulle pointeur de variables définies (par C99 et/ou C++98) si ils sont à la fois NULL - évalué?

Par exemple, disons que j'ai une mémoire tampon de la structure qui ressemble à ceci:

struct buf {
  char *buf;
  char *pwrite;
  char *pread;
} ex;

Dire, ex.buf de points à un tableau ou à certains malloc ed mémoire. Si mon code s'assure de toujours pwrite et pread point dans cette matrice ou un passé, alors je suis assez confiant qu' ex.pwrite - ex.pread sera toujours défini. Cependant, si pwrite et pread sont NULLES. Puis-je juste attendre soustrayant les deux est défini comme (ptrdiff_t)0 ou n'a strictement conforme code de la nécessité de tester les pointeurs NULL? Notez que le seul cas m'intéresse, c'est quand les deux pointeurs sont NULS (ce qui représente un tampon non initialisé cas). La raison a à voir avec un pleinement conforme "à disposition" de la fonction compte tenu des hypothèses précédentes sont remplies:

size_t buf_avail(const struct s_buf *b)
{     
    return b->pwrite - b->pread;
}

100voto

Adam Rosenfield Points 176408

En C99, il est techniquement un comportement indéfini. C99 §6.5.6 dit:

7) Pour l'application de ces opérateurs, un pointeur vers un objet qui n'est pas un élément d'une tableau se comporte comme un pointeur vers le premier élément d'un tableau de longueur avec le type de l'objet comme type d'élément.

[...]

9) Lorsque les deux pointeurs sont soustraits, à la fois doit pointer sur le même objet array, ou un au-delà du dernier élément du tableau d'objet, le résultat est à la différence de la les indices des deux éléments du tableau. [...]

Et §6.3.2.3/3 dit:

Une constante entière expression avec la valeur 0, ou une expression en fonte de type void *, est appelé un pointeur null constante.55) Si un pointeur null constante, est converti en un type pointeur le pointeur résultant, appelé un pointeur null, c'est la garantie de comparer l'inégalité à un pointeur sur un objet ou une fonction.

Donc, depuis un pointeur null est pas l'égal de n'importe quel objet, il viole les conditions de 6.5.6/9, donc c'est un comportement indéfini. Mais, dans la pratique, je serais prêt à parier que presque tous les compilateur renvoie un résultat de 0, sans aucun mauvais effets secondaires.

En C89, c'est aussi un comportement indéfini, si le libellé de la norme est légèrement différente.

C++03, d'autre part, n'ont comportement défini dans la présente instance. La norme établit une exception spéciale pour la soustraction de deux pointeurs null. C++03 §5.7/7 dit:

Si la valeur 0 est ajouté ou soustrait une valeur de type pointeur, le résultat se compare égale à l'original de la valeur du pointeur. Si deux pointeurs pointent sur le même objet ou à la fois un passé la fin de la même matrice, ou les deux, sont nuls, et les deux pointeurs de la soustraction, le résultat se compare égale à la valeur 0 converties dans le type ptrdiff_t.

C++11 (ainsi que la dernière version de C++14, n3690) ont un libellé identique à C++03, avec une modification mineure de l' std::ptrdiff_t à la place de ptrdiff_t.

36voto

Pubby Points 29386

J'ai trouvé ça dans la norme C++ (5.7 [expr.ajouter] / 7):

Si deux pointeurs [...] les deux sont nuls, et les deux pointeurs sont soustrait, le résultat se compare égale à la valeur 0 convertis à l' type std::ptrdiff_t

Comme d'autres l'ont dit, C99 nécessite l'addition/soustraction entre 2 pointeurs être de la même matrice de l'objet. NUL ne pointe pas vers un objet valide qui est pourquoi vous ne pouvez pas l'utiliser dans la soustraction.

23voto

Jens Gustedt Points 40410

Edit: Cette réponse n'est valable que pour le C, je n'ai pas vu le C++ tag quand j'ai répondu.

Non, l'arithmétique des pointeurs n'est autorisé que pour les pointeurs qui pointent dans le même objet. Puisque, par définition de la norme C pointeurs null ne pointez pas à n'importe quel objet, c'est un comportement indéfini.

(Bien que, je suppose que tout être raisonnable compilateur sera de retour juste 0 , mais qui sait.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X