2009-11-26 1 views
4

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

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

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?

+0

Вы должны явно передать результат сравнения в int. Поскольку вы используете% d, printf будет искать размер int (часто 4 байта) в стеке, но bool обычно составляет 1 байт. –

+0

Bipedal: правила продвижения C для функций vararg отлично справляются с этим, и что заставляет вас думать, что '==' приводит к bool вместо int в любом случае? : P –

+0

Согласно правилам преобразования vararg, 'bool' будет неявно повышаться до' int' при использовании в качестве аргумента vararg - см. 5.2.2 [expr.call]/7 и 4.5 [conv.prom]/4. –

ответ

20

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

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

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

+0

так это все из-за оптимизации компилятора? –

+2

Я уверен, что требование стандарта состоит в том, что идентичные строковые литералы в одной и той же системе перевода («файл», в стандартах) ** необходимы ** для того же места хранения. –

+0

В зависимости от архитектуры эти первые две строковые константы могут быть в защищенной от записи памяти и, следовательно, неизменяемы. Было бы разумно сократить требования к пространству, создав константу только один раз. –

4

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

1

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

+0

о, да, действительно верно; У меня все еще была «strcmp» в голове, и я перевернул значения! –

+0

Обновлено вопрос –

0

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

+0

'strcmp()' сравнивает строки – pmg

+0

Да, я знаю. :-) Я имел ввиду с операторами сравнения. :-) – Nosredna

2

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

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

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

То же самое для s3 == s4. Это «arrays decay into pointers» на работе.

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

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

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

+0

Да, это оптимизация пула строк. Я бы не стал на это рассчитывать. – Nosredna

Смежные вопросы