Сравнение массивов символов с помощью оператора == в C

StackOverflow https://stackoverflow.com/questions/1800816

  •  05-07-2019
  •  | 
  •  

Вопрос

Я знаю, что правильный способ сравнения «строк» ​​в 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 ?

Это было полезно?

Решение

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

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

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

Другие советы

Э-э ... когда == печатает 1, это означает, что они равны . Он отличается от 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("%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 означает истину, 0 означает ложь. Таким образом, ваше объяснение частично задом наперед. Что касается того, почему первые две строки кажутся одинаковыми: компилятор построил эту постоянную строку (s1 / 2) только один раз.

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

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

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

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

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

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

#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 указывают на один и тот же статический блок памяти, но я не ожидаю, что это поведение будет переносимым.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top