Quelle est la différence entre NULL, '' et 0

en C, il semble y avoir des différences entre diverses valeurs de zéro -- NULL , NUL et 0 .

je sais que le caractère ASCII '0' est évalué à 48 ou 0x30 .

le pointeur NULL est habituellement défini comme:

#define NULL 0

ou

#define NULL (void *)0

en outre, il y a le NUL caractère '"1519100920"' qui semble évaluer à 0 ainsi.

y a-t-il des moments où ces trois valeurs ne peuvent pas être égales?

est-ce aussi vrai sur les systèmes 64 bits?

244
demandé sur too honest for this site 2009-08-19 02:09:59

11 réponses

Note: cette réponse s'applique au langage C et non au langage C++.


Pointeurs Null

la constante entière littérale 0 a des significations différentes selon le contexte dans lequel elle est utilisée. Dans tous les cas, il est toujours une constante entière avec la valeur 0 , c'est juste décrit de différentes façons.

si un pointeur est comparé à constante littérale 0 , alors c'est une vérification pour voir si le pointeur est un pointeur null. Cette 0 est alors appelée constante de pointeur nulle. La norme C définit que 0 moulé au type void * est à la fois un pointeur nul et une constante de pointeur nul.

de plus, pour faciliter la lisibilité, la macro NULL est fournie dans le fichier d'en-tête stddef.h . Selon votre compilateur, il pourrait être possible de #undef NULL et redéfinir quelque chose de loufoque.

par conséquent, voici quelques façons valables de vérifier pour un pointeur null:

if (pointer == NULL)

NULL est défini pour comparer égal à un pointeur nul. Il est implémentation défini ce que la définition réelle de NULL est, tant qu'il s'agit d'une constante valide de pointeur null.

if (pointer == 0)

0 est une autre représentation de la constante de pointeur nulle.

if (!pointer)

cette if vérifie implicitement" n'est pas 0", donc nous inversons que pour signifier"est 0".

les moyens suivants sont invalides pour vérifier un pointeur nul:

int mynull = 0;
<some code>
if (pointer == mynull)

pour le compilateur ce n'est pas un contrôle pour un pointeur nul, mais un contrôle d'égalité sur deux variables. Ce pourrait fonctionne si mynull ne change jamais dans le code et la constante d'optimisation du compilateur plie le 0 dans le si déclaration, mais ce n'est pas garanti et que le compilateur doit produire au moins un message de diagnostic (avertissement ou erreur) selon la Norme.

notez qu'il s'agit d'un pointeur null en langage C. Il n'a pas d'importance sur l'architecture sous-jacente. Si l'architecture sous-jacente a une valeur de pointeur null définie comme l'adresse 0xDEADBEEF, alors c'est au compilateur de régler ce problème.

en tant que tel, même sur cette architecture Drôle, le les moyens suivants sont toujours valables pour vérifier un pointeur null:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

les moyens suivants sont invalides pour vérifier un pointeur nul:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

comme ceux-ci sont considérés par un compilateur comme des comparaisons normales.

Des Caractères Null

'"1519210920"' 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:

if (!*string_pointer)

vérifie si le pointeur de chaîne pointe vers un caractère nul

if (*string_pointer)

vérifie si le pointeur de chaîne pointe vers un caractère non nul

ne les confondez pas avec des pointeurs nuls. Juste parce que la représentation de bits est la même, et cela permet quelques cas croisés commodes, ils ne sont pas vraiment la même chose.

En outre, '"1519210920"' est (comme tous les caractères littéraux) une constante entière, dans ce cas avec la valeur zéro. Ainsi '" 1519210920 "' est tout à fait équivalent à une constante entière non ajustée 0 - la seule différence est dans le intention qu'il transmet à un lecteur humain ("je l'utilise comme un caractère nul.").

Références

Voir Question 5.3 de la comp.lang.C FAQ pour plus. Voir Ce pdf pour la norme C. Consultez la section 6.3.2.3, pointeurs, paragraphe 3.

290
répondu Andrew Keeton 2016-10-24 08:27:24

il semble qu'un certain nombre de personnes comprennent mal ce que sont les différences entre NULL, '\0' et 0. Donc, pour expliquer, et en essayant d'éviter de répéter les choses dit plus tôt:

une expression constante de type int avec la valeur 0, ou une expression de ce type, cast à type void * est une constante de pointeur nulle , qui si convertie en pointeur devient un pointeur nul . Il est garanti par la norme pour comparer les inégalités à un pointeur vers un objet ou une fonction .

"NULL est une macro, définie en tant que constante de pointeur null .

'\0' est une construction utilisée pour représenter le caractère null , utilisé pour terminer une chaîne de caractères.

Un caractère null est un octet, qui a tous ses bits à 0.

30
répondu amaterasu 2009-08-18 22:48:27

tous les trois définissent le sens du zéro dans un contexte différent.

  • contexte de pointeur-NULL est utilisé et signifie que la valeur du pointeur est 0, indépendamment du fait qu'il soit 32bit ou 64bit (un cas 4 octets Les 8 autres octets de zéros).
  • contexte de chaîne de caractères - le caractère représentant le chiffre zéro a une valeur hexadécimale de 0x30, tandis que le caractère NUL a une valeur hexadécimale de 0x00 (utilisé pour terminer les chaînes de caractères).

ces trois - là sont toujours différents quand on regarde la mémoire:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

j'espère que cela clarifie.

14
répondu Nasko 2017-09-22 19:27:34

si NULL et 0 sont équivalents en tant que constantes de pointeur null, que dois-je utiliser? dans le C FAQ de la liste des adresses de cette question:

C les programmeurs doivent comprendre que NULL et 0 sont interchangeables les contextes pointer, et qu'un uncast 0 est parfaitement acceptable. Toute utilisation de la Nul (par opposition à 0 ) devrait être considéré comme un rappel doux que pointeur est participants; programmeurs ne devrait pas en dépendre (ni pour leur propre compréhension ou l' compilateurs) pour distinguer les pointeurs 0 's à partir de l'entier 0 .

c'est seulement dans les contextes pointeurs que NULL et 0 sont équivalents. NULL devrait pas être utilisé lorsqu'un autre type de 0 est nécessaire, même si cela pourrait fonctionner, car cela envoie le mauvais message stylistique. (En outre, la norme ANSI permettre la définition de NULL à être ((void *)0) , qui ne fonctionnera pas à tous dans des contextes non pointeurs.) Dans en particulier, ne pas utiliser NULL lorsque la Le caractère ASCII null ( NUL ) est désiré. Donnez votre propre définition

#define NUL '"151900920"'

si vous le devez.

6
répondu Sinan Ünür 2009-08-18 22:38:25

Quelle est la différence entre NULL, ' \0’ et 0

"null character (NULL)" est le plus facile à exclure. '"151920920"' est un caractère littéral. En C , il est implémenté comme int , donc, c'est le même que 0, qui est de INT_TYPE_SIZE . En C++, le caractère littéral est implémenté comme char , qui est 1 byte. Ceci est normalement différent de NULL ou 0 .

suivant, NULL est un pointeur valeur qui spécifie qu'une variable ne pointe pas vers un espace d'adresse. Mis à part le fait qu'il est généralement mis en œuvre comme des zéros, il doit être capable d'exprimer l'adresse complète de l'espace de l'architecture. Ainsi, sur une architecture de 32 bits NULL (probable) est de 4 octets et sur une architecture de 64 bits 8 octets. Cela dépend de la mise en œuvre de C.

enfin, le littéral 0 est de type int , qui est de taille INT_TYPE_SIZE . La valeur par défaut de INT_TYPE_SIZE peut être différent en fonction de l'architecture.

Apple a écrit:

le modèle de données 64 bits utilisé par Mac OS X est connu sous le nom de"LP64". C'est le modèle de données commun utilisé par D'autres systèmes UNIX 64 bits de Sun et SGI ainsi que par Linux 64 bits. Le modèle de données LP64 définit les types primitifs comme suit:

  • entiers de 32 bits
  • les longueurs sont 64 bits
  • long-longs sont également 64 bits
  • pointeurs 64 bits

Wikipedia 64 bits :

le compilateur VC++ de Microsoft utilise le modèle LLP64.

64-bit data models
Data model short int long  long long pointers Sample operating systems
LLP64      16    32  32    64        64       Microsoft Win64 (X64/IA64)
LP64       16    32  64    64        64       Most Unix and Unix-like systems (Solaris, Linux, etc.)
ILP64      16    64  64    64        64       HAL
SILP64     64    64  64    64        64       ?

Modifier : Ajouté plus sur le caractère littéral.

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('"151910920"'));
    return 0;
}

le code ci-dessus renvoie 4 sur gcc et 1 sur g++.

5
répondu Eugene Yokota 2009-08-19 14:35:01

un NUL d'un litre, il termine une corde.

un nul de deux L ne signifie rien.

Et je parie une bulle d'or

Qu'il n'y a pas de trois-l NULLL.

Comment traitez-vous avec NUL?

3
répondu EvilTeach 2017-05-23 11:33:26

" NUL " n'est pas 0, mais fait référence au caractère ASCII NUL. Du moins, c'est comme ça que je l'ai vu utilisé. Le pointeur null est souvent défini comme 0, mais cela dépend de l'environnement dans lequel vous exécutez, et de la spécification de n'importe quel système d'exploitation ou langage que vous utilisez.

dans ANSI C, le pointeur nul est spécifié comme la valeur entière 0. Donc n'importe quel monde où ce n'est pas vrai n'est pas conforme à L'ANSI C.

2
répondu peterb 2009-08-18 22:16:47

Un bon morceau qui m'aide quand on a C(d'après l'Expert de la Programmation en C par Linden)

Le seul " l "nul et les Deux" l " null

Mémorisez cette petite rime pour rappeler la terminologie correcte pour les pointeurs et ASCII zéro:

The one "l" NUL ends an ASCII string,

The two "l" NULL points to no thing.

Apologies to Ogden Nash, but the three "l" nulll means check your spelling. 

le caractère ASCII avec le patron de bits de Zéro est appelé un"NUL". La valeur de pointeur spéciale que signifie que le pointeur nulle part n'est "nul". Les deux termes sont pas interchangeables dans sens.

2
répondu dlmeetei 2017-10-01 10:13:34

un octet avec une valeur de 0x00 est, sur la table ASCII, le caractère spécial appelé" NULL "ou"NULL". En C, puisque vous ne devriez pas intégrer de caractères de contrôle dans votre code source, cela est représenté dans les chaînes C avec un 0 échappé, i.e., "\0".

mais un vrai NULL est et non une valeur. C'est l'absence d'une valeur. Pour un pointeur, cela signifie que le pointeur n'a rien à point. Dans une base de données, il n'y a aucune valeur dans un champ qui n'est pas le même chose que de dire que le champ est vide, 0, ou rempli d'espaces).

la valeur réelle qu'un système donné ou un format de fichier de base de données utilise pour représenter un nul n'est pas nécessairement 0x00.

0
répondu richardtallent 2009-08-18 22:19:26

NULL n'est pas garanti à 0-sa valeur exacte dépend de l'architecture. La plupart des architectures majeures le définissent par (void*)0 .

'"151940920"' sera toujours égal à 0, car c'est ainsi que byte 0 est encodé dans un caractère littéral.

Je ne me souviens pas si les compilateurs C sont tenus d'utiliser ASCII -- sinon, '0' pourrait ne pas toujours égaler 48. Quoi qu'il en soit, il est peu probable que vous rencontrerez un jour un système qui utilise jeu de caractères alternatif comme EBCDIC sauf si vous travaillez sur très systèmes obscurs.

La taille des divers types diffèrent sur les systèmes 64 bits, mais les valeurs entières seront les mêmes.


certains commentateurs ont exprimé le doute que NULL soit égal à 0, mais pas be zéro. Voici un exemple de programme, avec les résultats attendus sur un tel système:

#include <stdio.h>

int main () {
    size_t ii;
    int *ptr = NULL;
    unsigned long *null_value = (unsigned long *)&ptr;
    if (NULL == 0) {
        printf ("NULL == 0\n"); }
    printf ("NULL = 0x");
    for (ii = 0; ii < sizeof (ptr); ii++) {
        printf ("%02X", null_value[ii]); }
    printf ("\n");
    return 0;
}

ce programme pourrait imprimer:

NULL == 0
NULL = 0x00000001
-1
répondu John Millikin 2009-08-18 22:59:37

(void*) 0 est nul, et '\0' représente la fin d'une chaîne.

-2
répondu shinxg 2017-09-20 08:41:10