Почему «а»! = «А» в C? - PullRequest
       14

Почему «а»! = «А» в C?

110 голосов
/ 30 января 2011
void main() {
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

Почему вывод No, not equal?

Ответы [ 11 ]

209 голосов
/ 30 января 2011

То, что вы сравниваете, это два адреса памяти для разных строк, которые хранятся в разных местах.По сути, это выглядит так:

if(0x00403064 == 0x002D316A) // Two memory locations
{
    printf("Yes, equal");
}

Используйте следующий код для сравнения двух строковых значений:

#include <string.h>

...

if(strcmp("a", "a") == 0)
{
    // Equal
}

Кроме того, "a" == "a" может действительно возвращать true, в зависимости от вашего компилятора,который может объединять одинаковые строки во время компиляции в одну для экономии места.

Когда вы сравниваете два символьных значения (которые не являются указателями), это числовое сравнение.Например:

'a' == 'a' // always true
52 голосов
/ 30 января 2011

Я немного опоздал на вечеринку, но я все равно отвечу; технически те же биты, но с бит другой точки зрения (на языке C ниже):

В C выражение "a" обозначает строковый литерал , который является статическим безымянным массивом const char, с длиной два - массив состоит из символов 'a' и '\0' - завершающий нулевой символ обозначает конец строки.

Однако в C таким же образом вы не можете передавать массивы в функции по значению - или присваивать им значения ( после инициализации ) - для массивов нет перегруженного оператора ==, поэтому это не так Можно сравнить их напрямую. Рассмотрим

int a1[] = {1, 2, 3};
int a2[] = {3, 4, 5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for
         // "identity", but not for their values. In this case the result
         // is always false, because the arrays (a1 and a2) are distinct objects

Если == не сравнивает массивы, что тогда он делает? В Си почти во всех контекстах, включая этот, массивы распадаются на указатели (которые указывают на первый элемент массива) - и сравнение указателей на равенство делает то, что вы ожидаете. Так эффективно, при этом

"a" == "a"

вы на самом деле сравниваете адреса первых символов в двух безымянных массивах . В соответствии со стандартом C сравнение может давать либо true, либо false (то есть 1 или 0) - "a" s может фактически обозначать один и тот же массив или два совершенно не связанных массива. В технических терминах результирующее значение равно неопределено , что означает, что сравнение разрешено (т. Е. Это не неопределенное поведение или синтаксическая ошибка), но любое значение допустимо и реализация (ваш компилятор) не требуется документировать, что на самом деле произойдет.

Как уже отмечали другие, для сравнения "строк c" (то есть строк, оканчивающихся нулевым символом) вы используете вспомогательную функцию strcmp, находящуюся в стандартном заголовочном файле string.h. Функция имеет возвращаемое значение 0 для одинаковых строк; Рекомендуется явно сравнивать возвращаемое значение с 0 вместо использования оператора `! ´, т.е.

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2)
47 голосов
/ 30 января 2011

Согласно С99 (раздел 6.4.5 / 6)

Строковые литералы

Не определено, различаются ли эти массивы при условии, что их элементы имеют соответствующие значения .

Так что в этом случае не определено, различны ли оба "a". Оптимизированный компилятор может хранить один "a" в доступном только для чтения месте, и обе ссылки могут ссылаться на него.

Проверьте вывод на gcc здесь

19 голосов
/ 30 января 2011

Поскольку они являются двумя отдельными const char*, указателями, а не фактическими значениями. Вы говорите что-то вроде 0x019181217 == 0x0089178216, что, конечно, возвращает НЕТ

Используйте strcmp() вместо ==

9 голосов
/ 31 января 2011

Проще говоря, в C нет встроенного оператора сравнения строк. Он не может сравнивать строки таким образом.

Вместо этого строки сравниваются с использованием стандартных библиотечных процедур, таких как strcmp (), или путем написания кода для циклического прохождения каждого символа в строке.

В Си строка текста в двойных кавычках возвращает указатель на строку. Ваш пример сравнивает указатели, и, по-видимому, две версии этой строки существуют по разным адресам.

Но это не сравнение самих строк, как вы, вероятно, ожидаете.

3 голосов
/ 30 января 2011

указка.

Первый "a" - указатель на строку ASCII с нулевым символом в конце.

Второй "a" является указателем на другую строку ASCII с нулевым символом в конце.

Если вы используете 32-битный компилятор, я бы ожидал "a"=="a"-4. Я только что попробовал это с tcc / Win32, и я получаю "a"=="a"-2. Ну да ладно ...

1 голос
/ 24 мая 2011

Вы сравниваете два адреса памяти, поэтому результат не всегда будет верным. Вы пробовали if('a' == 'a'){...}?

1 голос
/ 31 января 2011

этот вопрос устанавливает очень хороший путь объяснения для всех начинающих ....
позвольте мне также внести свой вклад в это .....

как все выше объяснили, почему вы получаете такой вывод.

сейчас, если вы хотите свою прогу. Чтобы напечатать "да равно", то

либо используйте

if(strcmp("a", "a") == 0)
{

}

или
не используйте «a» как строки, используйте их как символы ....

if('a'=='a')  
{  
printf ("yes Equal");  
}  

в символах C - 1-байтовое короткое целое число .......

0 голосов
/ 17 июля 2012

, если сравнение между символами всегда в одинарных кавычках, например,

if('a' == 'a')

и C не может поддерживать сравнение строк, например "abc" == "abc"

Это сделано с strcmp("abc","abc")

0 голосов
/ 27 июня 2012

Этот парень не использует переменные.Вместо этого он использует временно текстовые массивы: a и a.Причина, по которой

void main() 
{
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

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

char * text = "a";char * text2 = "a";

, тогда вы можете сравнить text с text2, и это должно быть true

Возможно, вы не должныне забудьте использовать { и } =)

void main() {
    if("a" == "a")
    {
      printf("Yes, equal");
    }
    else
    {
      printf("No, not equal");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...