Suis-je autorisé à utiliser le NULL
pointeur en remplacement de la valeur de 0
?
Ou y a-t-il quelque chose de mal à faire cela?
Comme par exemple:
int i = NULL;
en remplacement de:
int i = 0;
Comme expérience, j'ai compilé le code suivant:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Production:
0
En effet, il me donne cet avertissement, qui est tout à fait correct en soi:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
mais le résultat est toujours équivalent.
- Suis-je en train de passer à "Comportement indéfini" avec ça?
- Est-il permis d'utiliser
NULL
de cette manière? - Y a-t-il quelque chose de mal à utiliser
NULL
comme valeur numérique dans les expressions arithmétiques? - Et quel est le résultat et le comportement en C ++ dans ce cas?
J'ai lu les réponses de Quelle est la différence entre NULL, '\ 0' et 0 à propos de la différence entre NULL
, \0
et 0
est, mais je n'ai pas obtenu les informations concises à partir de là, si c'est tout à fait autorisé et aussi juste d'utiliser NULL
comme valeur à utiliser dans les affectations et autres opérations arithmétiques.
Réponses:
Non , ce n'est pas sûr de le faire.
NULL
est une constante de pointeur nul, qui pourrait avoir un typeint
, mais qui a plus généralement un typevoid *
(en C), ou autrement n'est pas directement assignable à unint
(en C ++> = 11). Les deux langages permettent aux pointeurs d'être convertis en entiers, mais ils ne prévoient pas que ces conversions soient effectuées implicitement (bien que certains compilateurs fournissent cela comme une extension). De plus, bien qu'il soit courant de convertir un pointeur nul en un entier pour donner la valeur 0, la norme ne le garantit pas. Si vous voulez une constante de typeint
et de valeur 0, épelez-la0
.Oui, sur toute implémentation où se
NULL
développe en une valeur de typevoid *
ou toute autre non directement assignableint
. La norme ne définit pas le comportement de votre affectation sur une telle implémentation, ergo son comportement n'est pas défini.C'est un style médiocre et il se cassera sur certains systèmes et dans certaines circonstances. Dans la mesure où vous semblez utiliser GCC, cela casserait votre propre exemple si vous compiliez avec l'
-Werror
option.Oui. Il n'est pas du tout garanti d'avoir une valeur numérique. Si vous voulez dire 0, écrivez 0, ce qui est non seulement bien défini, mais plus court et plus clair.
Le langage C ++ est plus strict sur les conversions que C et a des règles différentes pour
NULL
, mais là aussi, les implémentations peuvent fournir des extensions. Encore une fois, si vous voulez dire 0, c'est ce que vous devez écrire.la source
void *
" n'est vrai que pour C.void *
n'est pas un type légal pour C ++ (car vous ne pouvez pas l'affectervoid*
à un autre type de pointeur). En C ++ 89 et C ++ 03, ilNULL
doit en fait être de typeint
, mais dans les versions ultérieures il peut l'être (et l'est généralement)nullptr_t
.void*
enint
un comportement non défini. Ce n'est pas; il s'agit d'un comportement spécifié par l'implémentation.NULL
est une constante de pointeur nul. En C, il pourrait s'agir d'une expression constante entière avec valeur0
ou d'une telle expression transtypéevoid*
, cette dernière étant plus probable. Ce qui signifie que vous ne pouvez pas supposer utiliser deNULL
manière interchangeable avec zéro. Par exemple, dans cet exemple de codeLe remplacement
0
parNULL
n'est pas garanti être un programme C valide, car l'addition entre deux pointeurs (sans parler de types de pointeurs différents) n'est pas définie. Cela entraînera l'émission d'un diagnostic en raison d'une violation de contrainte. Les opérandes à ajouter ne seront pas valides .Quant au C ++, les choses sont quelque peu différentes. L'absence d'une conversion implicite de
void*
vers d'autres types d'objets signifiait qu'elleNULL
était historiquement définie comme0
dans le code C ++. En C ++ 03, vous pourriez probablement vous en tirer. Mais depuis C ++ 11, il peut êtrenullptr
légalement défini comme mot clé . Produisant à nouveau une erreur, carstd::nullptr_t
ne peut pas être ajouté aux types de pointeurs.Si
NULL
est défini comme tel,nullptr
même votre expérience devient invalide. Il n'y a pas de conversion destd::nullptr_t
en entier. C'est pourquoi elle est considérée comme une constante de pointeur nul plus sûre.la source
NULL
dans les deux langues.0
une constante de pointeur nul: "évidemment comme un sop à tout le code C mal écrit existant qui a fait des hypothèses incorrectes"Les règles varient selon les langues et leurs versions. Dans certains cas, vous pouvez et dans d'autres, vous ne pouvez pas. Quoi qu'il en soit, vous ne devriez pas . Si vous êtes chanceux, votre compilateur vous avertira lorsque vous tenterez de le faire ou mieux encore, ne parviendra pas à compiler.
En C ++, avant C ++ 11 (citation de C ++ 03):
Cela n'a pas de sens d'utiliser une constante de pointeur nul comme entier. Toutefois...
Donc, cela fonctionnerait techniquement même si c'est absurde. En raison de cette technicité, vous pouvez rencontrer des programmes mal écrits qui abusent
NULL
.Depuis C ++ 11 (citation du dernier projet):
A
std::nullptr_t
n'est pas convertible en entier, donc l'utilisation enNULL
tant qu'entier ne fonctionnerait que de manière conditionnelle, selon les choix effectués par l'implémentation du langage.PS
nullptr
est une valeur de typestd::nullptr_t
. Sauf si vous avez besoin de votre programme pour compiler en pré-C ++ 11, vous devez toujours utiliser à lanullptr
place deNULL
.C est un peu différent (citations du projet C11 N1548):
Ainsi, le cas est similaire au post C ++ 11 c'est-à-dire l'abus de
NULL
travaux conditionnellement en fonction des choix faits par l'implémentation du langage.la source
Oui , mais selon l'implémentation, vous aurez peut-être besoin d'un casting. Mais oui, c'est 100% légitime, sinon.
Bien que ce soit vraiment, vraiment, vraiment mauvais style (inutile de dire?).
NULL
est, ou était, en fait pas C ++, il est C. La norme ne cependant, comme pour de nombreux legs C, ont deux clauses ([diff.null] et [support.types.nullptr]) qui font techniquementNULL
C ++. Il s'agit d'une constante de pointeur nul définie par l'implémentation . Par conséquent, même si c'est un mauvais style, c'est techniquement aussi C ++ que possible.Comme indiqué dans la note de bas de page , les implémentations possibles pourraient être
0
ou0L
, mais pas(void*)0
.NULL
pourrait, bien sûr (la norme ne le dit pas explicitement, mais c'est à peu près le seul choix restant après0
ou0L
) êtrenullptr
. Ce n'est presque jamais le cas, mais c'est une possibilité légale.L'avertissement que le compilateur vous a montré montre que le compilateur n'est en fait pas conforme (sauf si vous avez compilé en mode C). Parce que, eh bien, selon l'avertissement, il a converti un pointeur nul (non
nullptr
qui serait denullptr_t
, qui serait distinct), donc apparemment la définition deNULL
est en effet(void*)0
, ce qu'elle peut ne pas être.Quoi qu'il en soit, vous avez deux cas légitimes possibles (c'est-à-dire que le compilateur n'est pas cassé). Soit (le cas réaliste),
NULL
est quelque chose comme0
ou0L
, alors vous avez des conversions "zéro ou un" en entier, et vous êtes prêt à partir.Ou
NULL
est en effetnullptr
. Dans ce cas, vous avez une valeur distincte qui offre des garanties de comparaison ainsi que des conversions clairement définies à partir d' entiers, mais malheureusement pas à des entiers. Il a cependant une conversion clairement définie enbool
(résultant enfalse
) etbool
une conversion clairement définie en entier (résultant en0
).Malheureusement, il s'agit de deux conversions, donc ce n'est pas dans "zéro ou un" comme indiqué dans [conv]. Ainsi, si votre implémentation se définit
NULL
commenullptr
, vous devrez ajouter un cast explicite pour que votre code soit correct.la source
De la faq C:
la source
Avertissement: je ne connais pas le C ++. Ma réponse n'est pas destinée à être appliquée dans le contexte de C ++
'\0'
est unint
avec une valeur nulle, juste 100% exactement comme0
.Dans le cadre des pointeurs ,
0
etNULL
sont 100% équivalents:sont tous 100% équivalents.
Remarque sur
ptr + NULL
Le contexte de
ptr + NULL
n'est pas celui des pointeurs. Il n'y a pas de définition pour l'ajout de pointeurs dans le langage C; des pointeurs et des entiers peuvent être ajoutés (ou soustraits). Dans leptr + NULL
cas où l'unptr
ou l' autreNULL
est un pointeur, l'autre doit être un entier, doncptr + NULL
est effectivement(int)ptr + NULL
ouptr + (int)NULL
et selon les définitions deptr
etNULL
plusieurs comportements peuvent être attendus: tout fonctionne, avertissement de conversion entre pointeur et entier, échec de compilation, .. .la source
#define NULL (void *)0
. Êtes-vous sûr que NULL et plain 0 sont 100% équivalents?ptr + NULL
n'utilise pasNULL
dans le contexte des pointeursnullptr
est, mais((void*)0)
et0
(ou'\0'
) sont équivalents dans le contexte des pointeurs ...if (ptr == '\0' /* or equivalent 0, NULL */)
Non,
NULL
je ne préfère plus utiliser (ancienne méthode d'initialisation du pointeur).Depuis C ++ 11:
Le mot clé
nullptr
désigne le littéral du pointeur. C'est une valeur de type std :: nullptr_t. Il existe des conversions implicites denullptr
en valeur de pointeur nulle de tout type de pointeur et de tout pointeur en type de membre. Des conversions similaires existent pour toute constante de pointeur nul, qui inclut des valeurs de typestd::nullptr_t
ainsi que la macroNULL
.https://en.cppreference.com/w/cpp/language/nullptr
En fait, std :: nullptr_t est le type du littéral de pointeur NULL,
nullptr
. Il s'agit d'un type distinct qui n'est pas lui-même un type de pointeur ou un pointeur sur le type de membre.Production:
la source