Quelle est la différence entre l'utilisation de (char)0
et '\0'
pour désigner le caractère nul final dans un tableau de caractères?
La notation barre oblique inverse dans un littéral de caractère vous permet de spécifier la valeur numérique d'un caractère au lieu d'utiliser le caractère lui-même. Alors '\1'
[*] signifie "le caractère dont la valeur numérique est 1", '\2'
signifie "le caractère dont la valeur numérique est 2", etc. Presque. En raison d'une particularité de C, les littéraux de caractères ont en fait le type int
, et en effet int
est également utilisé pour gérer les caractères dans d'autres contextes, tels que la valeur de retour de fgetc
. Alors '\1'
signifie "la valeur numérique sous la forme d'un entier, du caractère dont la valeur numérique est 1", etc.
Puisque les caractères sont des valeurs numériques en C, "le caractère dont la valeur numérique est 1" en fait est(char)1
, et la décoration supplémentaire dans '\1'
n'a aucun effet sur le compilateur - '\1'
a le même type et la même valeur que 1
in C. Ainsi, la notation barre oblique inverse est plus nécessaire dans les littéraux de chaîne que dans les littéraux de caractères, pour insérer des caractères non imprimables qui n'ont pas leur propre code d'échappement.
Personnellement, je préfère écrire 0
quand je veux dire 0, et laissez les conversions implicites faire leur travail. Certaines personnes trouvent cela très difficile à comprendre. Lorsque vous travaillez avec ces personnes, il est utile d'écrire '\0'
lorsque vous entendez un caractère de valeur 0, c'est-à-dire dans les cas où vous attendez votre 0
va bientôt se convertir implicitement en type char
. De même, il peut être utile d'écrire NULL
lorsque vous entendez une constante de pointeur nul, 0.0
lorsque vous voulez dire un double de valeur 0, etc.
Que cela fasse une différence pour le compilateur et qu'il ait besoin d'un cast, cela dépend du contexte. Puisque '\0'
a exactement le même type et la même valeur que 0
, il doit être converti en char
exactement dans les mêmes circonstances. Alors '\0'
et (char)0
diffèrent dans le type, pour des expressions exactement équivalentes, vous pouvez considérer (char)'\0'
contre (char)0
, ou '\0'
contre 0
. NULL
a un type défini par l'implémentation - il doit parfois être converti en type pointeur, car il peut avoir un type entier. 0.0
a le type double
, donc est certainement différent de 0
. Encore, float f = 1.0;
est identique à float f = 1;
et float f = 1.0f
, tandis que 1.0 / i
, où i
est un entier, a généralement une valeur différente de 1 / i
.
Donc, toute règle générale concernant l'utilisation de '\0'
ou 0
est purement pour la commodité des lecteurs de votre code - c'est la même chose pour le compilateur. Choisissez celui que vous (et vos collègues) préférez, ou définissez peut-être une macro ASCII_NUL
.
[*] ou '\01'
- puisque la barre oblique inverse introduit un nombre octal, pas décimal, il est parfois judicieux de rendre cela un peu plus évident en s'assurant qu'il commence par un 0. Cela ne fait aucune différence pour 0, 1, 2 bien sûr . Je dis "parfois", car la barre oblique inverse ne peut être suivie que de 3 chiffres octaux, vous ne pouvez donc pas écrire \0101
au lieu de \101
, pour rappeler au lecteur qu'il s'agit d'une valeur octale. Tout cela est assez gênant et conduit à encore plus de décoration: \x41
pour un A majuscule, et vous pourriez donc écrire '\x0'
pour 0 si vous le souhaitez.
Ils sont tous les deux un 0, mais (char) 0
est un caractère, tandis que '\0'
est (non intuitivement) un int
. Cette différence de type ne devrait généralement pas affecter votre programme si la valeur est 0.
Je préfère '\0'
, puisque c'est la constante prévue pour cela.
Zéro peut signifier beaucoup de choses différentes en C. Vous devez utiliser le caractère nul "\ 0", car il ne peut y avoir aucune confusion sur le fait que votre intention est la terminaison de chaîne.
Si vous définissez un caractère sur 0, cela peut signifier une terminaison nulle, mais cela peut également signifier que vous utilisez simplement le caractère comme un entier de 8 bits pour les calculs, plutôt que comme partie d'une chaîne. Cela peut être encore plus confus si vous utilisez également des pointeurs dans le même code et les comparez à zéro, qui est alors un pointeur nul.