Подтвердить что ты не робот

Почему нет ( "Maya" == "Maya" ) true в С++?

Любая идея, почему я получаю "Maya is not Maya" в результате для этого кода?

if ("Maya" == "Maya") 
   printf("Maya is Maya \n");
else
   printf("Maya is not Maya \n");
4b9b3361

Ответ 1

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

if (std::string("Maya") == "Maya") { /* ... */ } 
if (std::strcmp("Maya", "Maya") == 0) { /* ... */ }

Это потому, что С++ 03, §2.13.4 гласит:

Обычный строковый литерал имеет тип "array of n const char"

... и в вашем случае применяется преобразование в указатель.

См. также этот вопрос о том, почему вы не можете обеспечить перегрузку для == для этого случая.

Ответ 2

Вы не сравниваете строки, вы сравниваете равенство адреса указателя.

Чтобы быть более явным -

"foo baz bar" неявно определяет анонимный const char[m]. Реализовано определение того, будет ли идентичный анонимный const char [m] указывать на одно и то же место в памяти (концепция называется интернированием).

Функция, которую вы хотите - в C -, - strmp (char *, char *), которая возвращает 0 на равенство.

Или, на С++, что вы можете сделать, это

#include <string>

std::string s1 = "foo"

std::string s2 = "bar"

а затем сравните s1 vs. s2 с оператором ==, который интуитивно определен для строк.

Ответ 3

Результат вашей программы определяется реализацией.

Строковый литерал имеет тип const char[N] (то есть массив). Независимо от того, представлен ли каждый строковый литерал в вашей программе уникальным массивом, определяется ли реализация. (§2.13.4/2)

Когда вы выполняете сравнение, массивы распадаются на указатели (на первый элемент), и вы выполняете сравнение указателей. Если компилятор решает сохранить оба строковых литерала как один и тот же массив, указатели сравнивают true; если у каждого из них есть собственное хранилище, они сравнивают false.

Чтобы сравнить строку, используйте std::strcmp(), например:

if (std::strcmp("Maya", "Maya") == 0) // same

Обычно вы используете стандартный класс строк, std::string. Он определяет operator==. Вам нужно будет сделать один из ваших литералов std::string для использования этого оператора:

if (std::string("Maya") == "Maya") // same

Ответ 4

Что вы делаете, это сравнение адреса одной строки с адресом другого. В зависимости от компилятора и его настроек иногда одинаковые строки букв будут иметь один и тот же адрес, а иногда они не будут (как видимо, вы нашли).

Ответ 5

Любая идея, почему я получаю "Maya is not Maya" в результате

Поскольку в C и, следовательно, в С++ строковые литералы имеют тип const char[], который неявно преобразуется в const char*, указатель на первый символ, когда вы пытаетесь их сравнить. Сравнение указателей - сравнение адресов.
Независимо от того, сравниваются ли два строковых литерала одинаково или нет, зависит ли ваш компилятор (используя ваши текущие настройки) строковые литералы. Это разрешено делать, но это не нужно.,

Чтобы сравнить строки в C, используйте strcmp() из заголовка <string.h>. (Это std::strcmp() от <cstring> в С++.)

Чтобы сделать это на С++, проще всего превратить один из них в std::string (из заголовка <string>), который поставляется со всеми операторами сравнения, включая ==:

#include <string>

// ...

if (std::string("Maya") == "Maya") 
   std::cout << "Maya is Maya\n";
else
   std::cout << "Maya is not Maya\n";

Ответ 6

Мой компилятор говорит, что они одинаковы; -)

еще хуже, мой компилятор, безусловно, сломан. Это самое основное уравнение:

printf("23 - 523 = %d\n","23"-"523");

дает:

23 - 523 = 1

Ответ 7

C и С++ делают это сравнение с помощью сравнения указателей; похоже, что ваш компилятор создает отдельные экземпляры ресурсов для строк "Майя" и "Майя" (возможно, из-за отключения оптимизации).

Ответ 8

В самом деле, "потому что ваш компилятор в этом случае не использует пул строк", это технически правильный, но не особенно полезный ответ:)

Это одна из многих причин того, что класс std::string в стандартной библиотеке шаблонов существует для замены этого более раннего типа строки, когда вы хотите сделать что-нибудь полезное для строк на С++ и проблема почти всех, кто когда-либо учил C или С++, довольно рано спотыкается в своих исследованиях.

Позвольте мне объяснить.

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

Важнейшая часть здесь состоит в том, что хорошая старомодная "строка" C-стиля представляет собой массив символов в памяти. Этот блок памяти часто упоминается с помощью указателя - адреса начала блока памяти. Как правило, когда вы ссылаетесь на "строку" в C, вы обращаетесь к этому блоку памяти или указателю на него. C не имеет типа string; строки - это всего лишь группа char s в строке.

Когда вы пишете это в своем коде:

"wibble"

Затем компилятор предоставляет блок памяти, содержащий байты, представляющие символы 'w', 'i', 'b', 'b', 'l', 'e' и '\ 0' в этом порядке (компилятор добавляет нулевой байт в конце, "нулевой ограничитель". В C стандартная строка представляет собой строку с нулевым символом: блок символов, начинающийся с заданного адреса памяти и продолжающийся до следующего нулевого байта.)

И когда вы начинаете сравнивать подобные выражения, происходит следующее:

if ("Maya" == "Maya")

В точке этого сравнения компилятор - в вашем случае, в частности; см. мое объяснение пула строк в конце - создал два отдельных блока памяти, чтобы удерживать два разных набора символов, оба из которых установлены в 'M', 'a', 'y', 'a', '\ 0.

Когда компилятор видит строку в кавычках, подобную этой, "под капотом" строит массив символов, а сама строка "Майя" действует как имя массива символов. Поскольку имена массивов являются эффективными указателями, указывающими на первый символ массива, тип выражения "Майя" является указателем на char.

Когда вы сравниваете эти два выражения с использованием "==", то, что вы на самом деле сравниваете, это указатели, адреса памяти в начале этих двух разных блоков памяти. Именно поэтому сравнение в вашем конкретном случае является ложным с вашим конкретным компилятором.

Если вы хотите сравнить две хорошие старомодные строки C, вы должны использовать функцию strcmp(). Это рассмотрит содержимое памяти, обозначенное двумя "строками" (которые, как я уже объяснял, являются просто указателями на блок памяти) и просматривают байты, сравнивая их по одному и сообщая вам действительно ли они одинаковы.

Теперь, как я уже сказал, это немного неожиданный результат, который кусает новичков C на заднице со времен лет. И это одна из причин, по которой язык развивался с течением времени. Теперь в С++ существует класс std::string, который будет содержать строки и будет работать так, как вы ожидаете. Оператор "==" для std::string фактически сравнит содержимое двух std:: строк.

По умолчанию, однако, С++ предназначен для обратной совместимости с C, то есть программа C обычно компилируется и работает под компилятором С++ так же, как в компиляторе C, а это означает, что старомодные строки, "такие вещи, как это в вашем коде", по-прежнему окажутся в виде указателей на бит памяти, что даст неочевидным результатам новичка, когда вы начнете их сравнивать.

О, и что "пул пула" я упомянул в начале? То, где может возникнуть еще одна сложность. Умный компилятор, чтобы быть эффективным с его памятью, вполне может заметить, что в вашем случае строки одинаковы и не могут быть изменены и поэтому выделяют только один блок памяти, оба ваших имени, "майя", указывая на это. В этот момент сравнение "строк" ​​- указателей - скажет вам, что они, по сути, равны. Но больше удачи, чем дизайн!

Это поведение пула строк будет меняться от компилятора к компилятору и часто будет отличаться между режимами отладки и выпуска одного и того же компилятора, так как режим выпуска часто включает в себя такие оптимизации, которые делают код вывода более компактным (он должен иметь только один блок памяти с "майей", а не два, поэтому он сохранил пять - помните, что нулевой ограничитель! - байты в объектном коде.) И это поведение, которое может привести человека в бешенство, если они не знают, что происходит:)

Если ничего другого, этот ответ может дать вам много поисковых терминов для тысяч статей, которые уже есть в Интернете, пытаясь это объяснить. Это немного больно, и все проходят через это. Если вы можете получить голову вокруг указателей, вы станете намного лучше программистом на C или С++ в конечном итоге, независимо от того, хотите ли вы использовать std::string или нет!