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

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

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

11 ответов

Решение

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

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

Я немного опоздал на вечеринку, но я все равно отвечу; технически одни и те же биты, но с несколько иной точки зрения (на языке 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

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

"a" == "a"

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

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

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2)

В соответствии с C99(раздел 6.4.5/6)

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

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

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

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

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

использование strcmp() вместо ==

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

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

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

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

Указатели.

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

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

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

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

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

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

либо использовать

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

}

или же
не используйте "а" в качестве строк, используйте их как символы....

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

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

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

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

if('a' == 'a')

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

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

Некоторые компиляторы имеют опцию 'слияния строк', которую вы можете использовать, чтобы все константные строки имели одинаковый адрес. Если бы вы использовали это, "a" == "a" было бы true,

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

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

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

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

тогда вы могли бы сравнить text с text2и это должно быть правдой

Может быть, вы не должны забывать использовать { а также } знак равно

void main() {
    if("a" == "a")
    {
      printf("Yes, equal");
    }
    else
    {
      printf("No, not equal");
    }
}
Другие вопросы по тегам