Question

Je sais que la bonne façon de comparer les "chaînes". en C est en utilisant strcmp , mais j’ai maintenant essayé de comparer des tableaux de caractères à l’opérateur == et obtenu des résultats étranges.

Regardez le code suivant:

int main()
{
    char *s1 = "Andreas";
    char *s2 = "Andreas";

    char s3[] = "Andreas";
    char s4[] = "Andreas";

    char *s5 = "Hello";

    printf("%d\n", s1 == s2); //1
    printf("%d\n", s3 == s4); //0
    printf("%d\n", s1 == s5); //0
}

Le premier printf imprime correctement un 1 , ce qui indique qu'ils ne sont pas égaux. Mais quelqu'un peut-il m'expliquer pourquoi, lors de la comparaison des tableaux de caractères, le == renvoie un 0 ?

Quelqu'un peut-il m'expliquer s'il vous plaît pourquoi le premier printf renvoie un 1 (c'est-à-dire qu'ils sont égaux) et que les tableaux de caractères renvoient un 0 ?

Était-ce utile?

La solution

Le == compare l'adresse mémoire.
Il est probable que votre compilateur fait en sorte que s1 et s2 pointent sur les mêmes données statiques pour économiser de l'espace.

c'est à dire. Le " Andreas " dans les deux premières lignes de code est stocké dans vos données exécutables. Le standard C dit que ces chaînes sont constantes et a donc optomisé les deux pointeurs pour qu'ils pointent vers le même stockage.

Les lignes char [] créent une variable en copiant les données dans la variable et sont donc stockées à une adresse différente sur la pile pendant l'exécution.

Autres conseils

Euh ... quand == imprime un 1, cela signifie qu'ils sont égaux. C'est différent de strcmp, qui renvoie l'ordre relatif des chaînes.

Vous comparez des adresses et non des chaînes. Les deux premiers sont constants et ne seront créés qu'une fois.

int main()
{
    char *s1 = "Andreas";
    char *s2 = "Andreas";

    char s3[] = "Andreas";
    char s4[] = "Andreas";

    char *s5 = "Hello";

    printf("%d\n", s1 == s2); //1
    printf("%p == %p\n", s1, s2);
    printf("%d\n", s3 == s4); //0
    printf("%p != %p\n", s3, s4);
    printf("%d\n", s1 == s5); //0
    printf("%p != %p\n", s1, s5);
}

Sortie sur mon ordinateur, mais vous avez l’idée:

1
0x1fd8 == 0x1fd8
0
0xbffff8fc != 0xbffff8f4
0
0x1fd8 != 0x1fe0

Attendez une seconde ... 1 signifie vrai, 0 signifie faux. Votre explication est donc partiellement à l’arrière. Pourquoi les deux premières chaînes semblent-elles égales? Le compilateur a construit cette chaîne constante (s1 / 2) une seule fois.

s1 == s2 signifie " (car *) == (car *) ". ou que les adresses sont les mêmes.

Même chose pour s3 == s4 . C’est la " la décomposition des tableaux en pointeurs " au travail.

Et vous avez une mauvaise signification du résultat de la comparaison:

0 == 0; /* true; 1 */
42 == 0; /* false; 0 */
"foo" == "bar"; /* false (the addresses are different); 0 */

Toutes les valeurs de s1 à s5 ne sont pas char , mais des pointeurs vers char . Vous comparez donc les adresses mémoire de chaque chaîne, plutôt que les chaînes elles-mêmes.

Si vous affichez les adresses de cette manière, vous pourrez voir sur quoi les opérateurs de comparaison travaillent réellement:

#include <stdio.h>

int main() {
  char *s1 = "Andreas";
  char *s2 = "Andreas";

  char s3[] = "Andreas";
  char s4[] = "Andreas";

  char *s5 = "Hello";

  printf("%p\n", s1); // 0x80484d0
  printf("%p\n", s2); // 0x80484d0
  printf("%p\n", s3); // 0xbfef9280
  printf("%p\n", s4); // 0xbfef9278
  printf("%p\n", s5); // 0x80484d8
}

Le lieu exact où les chaînes sont allouées en mémoire est spécifique à la mise en oeuvre. Dans ce cas, les s1 et s2 pointent vers le même bloc de mémoire statique, mais je ne m'attendrais pas à ce que ce comportement soit portable.

Vous ne pouvez pas comparer les chaînes, mais vous pouvez comparer les pointeurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top