Inspiré par un programme décrit dans K&R section 5.5:
void strcpy(char *s, char *t)
{
while(*s++ = *t++);
}
Programme C
if ('\0') { printf("\'\\0\' -> true \n"); }
else { printf("\'\\0\' -> false\n"); }
if ("\0") { printf("\"\\0\" -> true \n"); }
else { printf("\"\\0\" -> false\n"); }
impressions
'\0' -> false
"\0" -> true
Pourquoi faire '\0'
et "\0"
évaluer différemment en C?
clang version 3.8.0
Rappelez-vous comment fonctionnent les littéraux de chaîne en C - "\0"
est un tableau de caractères contenant deux octets zéro (celui que vous avez demandé et celui implicite à la fin). Lorsqu'il est évalué pour le test if
, il se désintègre en un pointeur sur son premier caractère. Ce pointeur n'est pas NULL, il est donc considéré comme vrai lorsqu'il est utilisé comme condition.
'\0'
est le nombre zéro, équivalent à seulement 0
. C'est un entier qui est zéro, il est donc considéré comme faux lorsqu'il est utilisé comme condition.
Tout d'abord, vous devez garder à l'esprit qu'en C,
NULL
est faux et nonNULL
est vrai.'\0'
, comme d'autres l'ont dit, est le même que le littéral entier 0
et est donc faux (voir le premier point ci-dessus pour savoir pourquoi).
"\0"
est un littéral de chaîne qui contient deux \0
caractères (l'un que vous avez explicitement ajouté et l'autre, qui est implicite et sera ajouté par le compilateur). Le littéral de chaîne sera stocké quelque part dans la mémoire morte. Lorsque vous utilisez "\0"
, il est converti en pointeur vers son premier élément †. Ceci est communément appelé " désintégration du tablea ". (C'est la raison pour laquelle des trucs comme char* str = "string";
travaux).
Donc, vous vérifiez effectivement l'adresse du premier caractère de la chaîne littérale . Puisque l'adresse du littéral de chaîne sera toujours non -NULL
, le if sera toujours vrai (Voir la deuxième puce ci-dessus pour savoir pourquoi).
†: Cette "désintégration" des tableaux ne se produit pas toujours. Voir Exception au tableau ne se décomposant pas en un pointeur?
'\0'
est un nombre: 0
, il est donc évalué comme faux (0
= faux, !0
= vrai).
Mais "\0"
est un pointeur vers une section en lecture seule où la chaîne réelle est stockée, le pointeur n'est pas NULL
ergo c'est vrai.
Tout d'abord, en regardant les deux conditions, '\0'
est une constante de type entier, qui désigne le caractère nul C, qui est le même que 0
. Tandis que "\0"
est un littéral de chaîne, qui contient 2 octets, celui spécifié et l'octet de terminaison nul implicitement ajouté. Étant un littéral de chaîne, le pointeur ne peut pas être NULL
.
Deuxièmement, en C, pour la condition de l'instruction if
, tout ce qui n'est pas nul est évalué comme true
, et zéro est évalué comme false
.
Selon cette règle, il sera clair que '\0'
est false
et "\0"
évalué comme true
.
Tout d'abord, veuillez noter que la valeur hexadécimale de False est 0x00
et True est toute autre valeur que 0x00.
"\0"
est une chaîne avec un caractère et Null Terminator '\0'
à la fin. Il s'agit donc d'un pointeur de caractères pointant vers un tableau de 2 octets: ['\0', '\0']
. Dans ce tableau, le premier est le caractère et l'autre est le terminateur nul.
Après la compilation (sans optimisation), ce pointeur de caractère est temporairement affecté à une adresse en mémoire pointant vers le premier octet de ces deux octets. Cette adresse peut être, par exemple, 0x18A6
en hexadécimal. Le compilateur (la plupart d'entre eux) écrit donc ces deux valeurs dans la mémoire. Parce qu'une chaîne est en fait l'adresse du premier octet de cette chaîne, notre expression est interprétée comme 0x18A6 != false
. Donc, c'est clair 0x18A6 != 0x00
est vrai.
'\0'
est simplement 0x00
en hexadécimal. 0x00 != 0x00
c'est faux.
Cette réponse est écrite pour une architecture de données 8 bits avec un adressage 16 bits. J'espère que ça aide.
Découvrez cela avec des exemples ..
#include <stdio.h>
int main()
{
printf( "string value\n" );
//the integer zero
printf( "0.........%d\n" , 0 );
//the char zero, but chars are very small ints, so it is also an int
//it just has some special syntax and conventions to allow it to seem
//like a character, it's actual value is 48, this is based on the
//ASCII standard, which you can look up on Wikipedia
printf( "'0'.......%d\n" , '0' );
//because it is an integer, you can add it together,
//'0'+'0' is the same as 48+48 , so it's value is 96
printf( "'0'+'0'...%d\n" , '0'+'0' );
//the null terminator, this indicates that it is the end of the string
//this is one of the conventions strings use, as a string is just an array
//of characters (in C, at least), it uses this value to know where the array
//ends, that way you don't have to lug around another variable to track
//how long your string is. The actual integer value of '\0' is zero.
printf( "'\\0'......%d\n" , '\0' );
//as stated, a string is just an array of characters, and arrays are tracked
//by the memory location of their first index. This means that a string is
//actually a pointer to the memory address that stores the first element of
//the string. We should get some large number, a memory address
printf( "\"0\".......%d\n" , "0" );
//a string is just an array of characters, so lets access the character
//in position zero of the array. it should be the character zero, which
//has an integer value of 48
printf( "\"0\"[0]....%d\n" , "0"[0] );
//and the same thing for the empty string
printf( "\"\\0\"[0]...%d\n" , "\0"[0] ); //equal to '\0'
//we also said a string is just a pointer, so we should be able to access
//the value it is pointing to (the first index of the array of characters)
//by using pointers
printf( "*\"0\"......%d\n" , *"0" );
return 0;
}
'\ 0' est un caractère null qui a la valeur . Il est utilisé pour terminer une chaîne de caractères. C'est donc considéré comme faux.
"\ 0" est un null ou videchaîne. Le seul caractère de la chaîne est le caractère nul qui termine la chaîne, il est donc considéré comme vrai.
'\ 0' est un caractère égal au nombre zéro. "\ 0" est une chaîne et nous ajoutons généralement '\ 0' à la fin d'une chaîne. N'utilisez pas '\ 0' ou "\ 0" dans une instruction conditionnelle car c'est assez déroutant.
L'utilisation suivante est suggérée:
if (array[0] != 0)
{
}
if (p != 0)
{
}
if (p != NULL)
{
}
Nous pouvons effacer le problème ci-dessus dans deux concept différents de C
1. Travail de if (condition) en C if (condition)
En langage C, si la condition fonctionne sur 0(Zero) et base non nulle.
Si le résultat de la condition donnée est zéro, alors C considère que la condition donnée est fausse.
Si le résultat de la condition donnée est non nul, alors C considère que la condition donnée est vraie.
2. Différence des littéraux de caractères et de chaînes en C
En C, les littéraux chaîne sont ceux qui sont entourés de guillemets doubles (""), tandis que les littéraux caractère sont ceux qui sont entourés de guillemets simples ('') et la longueur minimale est d'un caractère et la longueur maximale est de deux caractères.
Un autre point important est qu'en C, si nous convertissons '\ 0' (null) en int (Integer), alors nous obtiendrons 0 (Zero), alors que nous ne pouvons pas convertir "\ 0" en int implicitement ou explicitement. Parce que "\ 0" est une chaîne tandis que '\ 0' est un caractère.
Et selon la logique de fonctionnement de la condition IF de chaîne, si la condition renvoie 0 ou faux, cela signifie que la condition est fausse; si la condition retourne non nulle, cela signifie que la condition est vraie.
Donc, selon les points 1 et 2, nous pouvons enfin conclure que
if ('\ 0') printf ("\ '\ 0 \'! = false\n"); // la condition devient fausse
if ("\ 0") printf ("\"\0\"! = false\n"); // la condition devient vraie
La chose simple est ATLEAST 0 (int) et 0.0 (float ou double) ont une valeur FAUX en C.
'\ 0' est un entier 0.
"\ 0" est un tableau de caractères. Il N'importe pas À L'INTÉRIEUR du tableau combien de caractères sont là ou quels sont ces caractères.
Ainsi, '\ 0' est évalué à 0 comme 77-77 est évalué à 0. Et 0 est faux.
int x; x = '\0'; printf("X has a value : %d");
Sortie:
x a une valeur: 0
Et le code:
if(0){printf("true");}
else{printf("false");}
Production:
false