Сравнение массивов символов с оператором == в C - PullRequest
4 голосов
/ 26 ноября 2009

Я знаю, что правильный способ сравнения «строк» ​​в C - это использование strcmp, но теперь я попытался сравнить некоторые массивы символов с оператором == и получил странные результаты.

Взгляните на следующий код:

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
}

Первый printf правильно печатает 1, что означает, что они не равны. Но может ли кто-нибудь объяснить мне, почему при сравнении массивов символов == возвращает 0?

Может кто-нибудь объяснить мне, почему первый printf возвращает 1 (т.е. они равны), а массивы символов возвращают 0?

Ответы [ 7 ]

20 голосов
/ 26 ноября 2009

== сравнивает адрес памяти.
Вероятно, ваш компилятор заставляет s1 и s2 указывать на одни и те же статические данные для экономии места.

есть. «Андреас» в первых двух строках кода хранится в ваших исполняемых данных. Стандарт C говорит, что эти строки постоянны, и поэтому два указателя указали на одно и то же хранилище.

Строки char [] создают переменную путем копирования данных в переменную и, таким образом, сохраняются по другому адресу в стеке во время выполнения.

4 голосов
/ 26 ноября 2009

Э-э ... когда == печатает 1, это означает, что они равны . Он отличается от strcmp, который возвращает относительный порядок строк.

2 голосов
/ 26 ноября 2009

Вы сравниваете адреса, а не строки. Первые два являются постоянными и будут созданы только один раз.

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);
}

Вывод на мой компьютер, но вы поняли:

1
0x1fd8 == 0x1fd8
0
0xbffff8fc != 0xbffff8f4
0
0x1fd8 != 0x1fe0
1 голос
/ 26 ноября 2009

Все значения от s1 до s5 сами по себе не char , они указатели на char . Итак, вы сравниваете адреса памяти каждой строки, а не сами строки.

Если вы отобразите адреса таким образом, вы увидите, над чем в действительности работают операторы сравнения:

#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
}

Точное расположение строк в памяти зависит от конкретной реализации. В этом случае s1 и s2 указывают на один и тот же статический блок памяти, но я не ожидаю, что это поведение будет переносимым.

1 голос
/ 26 ноября 2009

s1 == s2 означает «(char*) == (char*)» или адреса совпадают.

То же самое для s3 == s4. Это " массивы распадаются на указатели " на работе.

А у вас неверный смысл результата сравнения:

0 == 0; /* true; 1 */
42 == 0; /* false; 0 */
"foo" == "bar"; /* false (the addresses are different); 0 */
1 голос
/ 26 ноября 2009

Подождите секунду ... 1 означает истину, 0 означает ложь. Таким образом, ваше объяснение частично задом наперед. Что касается того, почему первые две строки кажутся одинаковыми: компилятор построил эту постоянную строку (s1 / 2) только один раз.

0 голосов
/ 26 ноября 2009

Вы не можете сравнивать строки, но вы можете сравнивать указатели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...