En C, il semble y avoir des différences entre les différentes valeurs de zéro - NULL
, NUL
et 0
.
Je sais que le caractère ASCII correspond '0'
à 48
ou 0x30
.
Le NULL
pointeur est généralement défini comme:
#define NULL 0
Ou
#define NULL (void *)0
De plus, il y a le NUL
personnage '\0'
qui semble également évaluer 0
.
Y a-t-il des moments où ces trois valeurs ne peuvent pas être égales?
Est-ce également vrai sur les systèmes 64 bits?
NUL
n'existe pas dans le langage ou la bibliothèque standard C (ou en C ++ pour autant que je sache). Le caractère nul est parfois appelé NUL, mais il est généralement appelé C ou C ++'\0'
.Réponses:
Remarque: Cette réponse s'applique au langage C, pas à C ++.
Pointeurs nuls
Le littéral de constante entière
0
a des significations différentes selon le contexte dans lequel il est utilisé. Dans tous les cas, c'est toujours une constante entière avec la valeur0
, elle est juste décrite de différentes manières.Si un pointeur est comparé au littéral constant
0
, il s'agit d'une vérification pour voir si le pointeur est un pointeur nul. Ceci0
est alors appelé une constante de pointeur nul. La norme C définit que la0
conversion en typevoid *
est à la fois un pointeur nul et une constante de pointeur nul.De plus, pour améliorer la lisibilité, la macro
NULL
est fournie dans le fichier d'en-têtestddef.h
. Selon votre compilateur, il peut être possible de le#undef NULL
redéfinir en quelque chose de farfelu.Par conséquent, voici quelques moyens valides de rechercher un pointeur nul:
NULL
est défini pour comparer égal à un pointeur nul. C'est l'implémentation définie quelle est la définition réelle deNULL
, tant qu'il s'agit d'une constante de pointeur null valide.0
est une autre représentation de la constante de pointeur nul.Cette
if
instruction vérifie implicitement "n'est pas 0", donc nous inversons cela pour signifier "est 0".Les méthodes suivantes sont INVALIDES pour rechercher un pointeur nul:
Pour le compilateur, ce n'est pas une vérification pour un pointeur nul, mais une vérification d'égalité sur deux variables. Cela peut fonctionner si mynull ne change jamais dans le code et la constante d'optimisation du compilateur replie le 0 dans l'instruction if, mais cela n'est pas garanti et le compilateur doit produire au moins un message de diagnostic (avertissement ou erreur) selon la norme C.
Notez que ce qui est un pointeur nul dans le langage C. Peu importe l'architecture sous-jacente. Si l'architecture sous-jacente a une valeur de pointeur nulle définie comme adresse 0xDEADBEEF, alors c'est au compilateur de trier ce gâchis.
En tant que tel, même sur cette architecture amusante, les moyens suivants sont toujours des moyens valides de rechercher un pointeur nul:
Les méthodes suivantes sont INVALIDES pour rechercher un pointeur nul:
car ceux-ci sont vus par un compilateur comme des comparaisons normales.
Personnages nuls
'\0'
est défini comme un caractère nul - c'est-à-dire un caractère dont tous les bits sont mis à zéro. Cela n'a rien à voir avec les pointeurs. Cependant, vous pouvez voir quelque chose de similaire à ce code:vérifie si le pointeur de la chaîne pointe sur un caractère nul
vérifie si le pointeur de la chaîne pointe sur un caractère non nul
Ne les confondez pas avec des pointeurs nuls. Tout simplement parce que la représentation des bits est la même, et cela permet des cas de croisement pratiques, ce n'est pas vraiment la même chose.
De plus,
'\0'
est (comme tous les littéraux de caractères) une constante entière, dans ce cas avec la valeur zéro.'\0'
Est donc complètement équivalent à une0
constante entière sans fioritures - la seule différence est dans l' intention qu'elle transmet à un lecteur humain ("J'utilise ceci comme un caractère nul.").Références
Voir la question 5.3 de la FAQ comp.lang.c pour plus d'informations. Voir ce pdf pour la norme C. Consultez les sections 6.3.2.3 Pointeurs, paragraphe 3.
la source
ptr
à tous les bits à zéro . Ce n'est pas unmemcmp
, mais c'est une comparaison utilisant un opérateur intégré. L'un côté est une constante de pointeur nul'\0'
et l'autre côté est un pointeur. Ainsi qu'avec les deux autres versions avecNULL
et0
. Ces trois-là font la même chose.0xDEADBEEF
toujours un pointeur NULL, peu importe ce que ses regards aiment chaîne binaire, et il comparera toujours égal àNULL
,0
,\0
et toutes les autres formes de constantes pointeur NULL.ptr == '\0'
.Il semble qu'un certain nombre de personnes comprennent mal les différences entre NULL, «\ 0» et 0. Donc, pour expliquer, et pour éviter de répéter les choses, on a dit plus tôt:
Une expression constante de type
int
avec la valeur 0, ou une expression de ce type, transtypée en type,void *
est une constante de pointeur nulle qui, si elle est convertie en pointeur, devient un pointeur nul. . Il est garanti par la norme de comparer l' inégalité à tout pointeur à tout objet ou fonction .NULL
est une macro, définie en tant que constante de pointeur nul .\0
est une construction utilisée pour représenter le caractère nul , utilisée pour terminer une chaîne.Un caractère nul est un octet dont tous ses bits sont mis à 0.
la source
Les trois définissent la signification de zéro dans un contexte différent.
Ces trois sont toujours différents quand on regarde la mémoire:
J'espère que cela clarifie les choses.
la source
sizeof('\0')
et soyez surpris.Si NULL et 0 sont équivalents en tant que constantes de pointeur nul, que dois-je utiliser? dans la liste FAQ C résout également ce problème:
la source
"caractère nul (NUL)" est plus facile à exclure.
'\0'
est un caractère littéral. En C, il est implémenté commeint
, donc, c'est la même chose que 0, qui est deINT_TYPE_SIZE
. En C ++, le littéral de caractères est implémenté en tant quechar
, ce qui correspond à 1 octet. Ceci est normalement différent deNULL
ou0
.Prochain,
NULL
est une valeur de pointeur qui spécifie qu'une variable ne pointe vers aucun espace d'adressage. Mis à part le fait qu'il est généralement implémenté sous forme de zéros, il doit pouvoir exprimer l'espace d'adressage complet de l'architecture. Ainsi, sur une architecture 32 bits NULL (probable) est de 4 octets et sur une architecture 64 bits de 8 octets. Cela dépend de la mise en œuvre de C.Enfin, le littéral
0
est de typeint
, qui est de tailleINT_TYPE_SIZE
. La valeur par défaut deINT_TYPE_SIZE
pourrait être différente selon l'architecture.Apple a écrit:
Wikipédia 64 bits :
Edit : Ajout de plus sur le littéral de caractère.
Le code ci-dessus renvoie 4 sur gcc et 1 sur g ++.
la source
'\0'
n'est pas une valeur à 1 octet. C'est un littéral de caractère, qui est une expression constante entière - donc s'il peut être dit qu'il a une taille, c'est la taille d'unint
(qui doit être d'au moins 2 octets). Si vous ne me croyez pas, évaluezsizeof('\0')
et voyez par vous-même.'\0'
,0
Et0x0
sont tous complètement équivalents.sizeof('\0')
un compilateur C ++.Un NUL d'un L, il termine une chaîne.
Un NULL de deux L ne signifie rien.
Et je parierai un taureau d'or
Qu'il n'y a pas de NULLL de trois litres.
Comment gérez-vous NUL?
la source
Un bon morceau qui m'aide lorsque je commence par C (extrait de la programmation Expert C de Linden)
Le One 'l' nul et le Two 'l' null
Mémorisez cette petite rime pour rappeler la terminologie correcte pour les pointeurs et zéro ASCII:
Le caractère ASCII avec la configuration binaire de zéro est appelé "NUL". La valeur spéciale du pointeur qui signifie que le pointeur n'est nulle part "NULL". Les deux termes ne sont pas interchangeables dans leur sens.
la source
NUL
est un code de commande tel queBEL
,VT
,HT
,SOT
etc. et a donc max. 3 caractères."NUL" n'est pas 0, mais fait référence au caractère ASCII NUL. C'est du moins ainsi que je l'ai vu utilisé. Le pointeur nul est souvent défini sur 0, mais cela dépend de l'environnement dans lequel vous exécutez et de la spécification du système d'exploitation ou de la langue que vous utilisez.
Dans ANSI C, le pointeur nul est spécifié comme la valeur entière 0. Ainsi, tout monde où ce n'est pas vrai n'est pas conforme à ANSI C.
la source
Un octet avec une valeur de
0x00
est, sur la table ASCII, le caractère spécial appeléNUL
ouNULL
. En C, puisque vous ne devez pas incorporer de caractères de contrôle dans votre code source, cela est représenté dans les chaînes C avec un 0 d'échappement, c'est-à-dire\0
.Mais un vrai NULL n'est pas une valeur. C'est l'absence de valeur. Pour un pointeur, cela signifie que le pointeur n'a rien à pointer. Dans une base de données, cela signifie qu'il n'y a pas de valeur dans un champ (ce qui n'est pas la même chose que de dire que le champ est vide, 0 ou rempli d'espaces).
La valeur réelle qu'un format de fichier système ou base de données donné utilise pour représenter un
NULL
n'est pas nécessairement0x00
.la source
NULL
n'est pas garanti comme étant 0 - sa valeur exacte dépend de l'architecture. La plupart des architectures majeures le définissent(void*)0
.'\0'
sera toujours égal à 0, car c'est ainsi que l'octet 0 est codé dans un littéral de caractère.Je ne me souviens pas si les compilateurs C sont tenus d'utiliser ASCII - sinon, ils
'0'
ne sont pas toujours égaux à 48. Quoi qu'il en soit, il est peu probable que vous rencontriez un système qui utilise un jeu de caractères alternatif comme EBCDIC à moins que vous ne travailliez très systèmes obscurs.Les tailles des différents types différeront sur les systèmes 64 bits, mais les valeurs entières seront les mêmes.
Certains commentateurs ont exprimé des doutes que NULL soit égale à 0, mais pas être nul. Voici un exemple de programme, ainsi que les résultats attendus sur un tel système:
Ce programme pourrait imprimer:
la source
(void *) 0 est NULL et '\ 0' représente la fin d'une chaîne.
la source