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