сравнение между строковым литералом - PullRequest
4 голосов
/ 18 марта 2010

Это очень простой код:

#include <iostream>

using namespace std;

void exec(char* option)
{
    cout << "option is " << option << endl;
    if (option == "foo")
        cout << "option foo";
    else if (option == "bar")
        cout << "opzion bar";
    else
        cout << "???";
    cout << endl;
}

int main()
{
    char opt[] = "foo";
    exec(opt);
    return 0;
}

генерирует два предупреждения: сравнение со строковым литералом приводит к неопределенному поведению.

Можете ли вы объяснить, почему именно этот код не работает, но если я изменю

char opt[]

до

char *opt

это работает, но выдает предупреждение? Это связано с завершением \ 0? В чем разница между двумя декларациями opt? Что если я использую константный квалификатор? Решением является использование std :: string?

Ответы [ 5 ]

12 голосов
/ 18 марта 2010

char-массивы или указатели char на самом деле не то же самое, что строковые объекты класса в C ++, так что

if (option == "foo")

Не сравнивает строку option со строковым литералом "foo", сравнивает адрес из option с адресом строкового литерала "foo" Вам нужно использовать одну из многих функций сравнения строк, если вы хотите узнать, совпадает ли опция с "foo". strcmp является очевидным способом сделать это, или вы можете использовать std::string вместо char*

2 голосов
/ 18 марта 2010

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

Причина, по которой он может работать при использовании char *, заключается в том, что компилятор может решить один раз сохранить буквенную строку "opt" и повторно использовать ее для обеих ссылок (я уверен, что видел компилятор установка где-нибудь, что указывает, делает ли это компилятор).

В случае char opt [] компилятор копирует строковый литерал в область хранения, зарезервированную для массива opt (возможно, в стеке), что приводит к разным указателям.

Renze

2 голосов
/ 18 марта 2010

Вы можете использовать оператор == для сравнения строк, только если вы используете std::string (что является хорошей практикой). Если вы используете строки char * / char [] в стиле C, вам нужно использовать функции C strcmp или strncmp.

Вы также можете использовать std::string::operator == для сравнения std::string со строкой C:

std string foo = "foo";
const char *bar = "bar";

if (foo == bar) 
   ...
0 голосов
/ 18 марта 2010

Для C ++ я бы использовал решение std :: string :

#include <iostream> 
#include <string>

using namespace std; 

void exec(string option) 
{ 
    cout << "option is " << option << endl; 
    if (option == "foo") 
        cout << "option foo"; 
    else if (option == "bar") 
        cout << "option bar"; 
    else 
        cout << "???"; 
    cout << endl; 
} 

int main() 
{ 
    string opt = "foo"; 
    exec(opt);

    exec("bar");

    char array[] = "other";
    exec(array);
    return 0; 
} 

std :: string знает, как создать себя из char [], char * и т. Д., Поэтому вы все равно можете вызывать функцию и этими способами.

0 голосов
/ 18 марта 2010

Похоже, вы пришли из Java / C # :) В C ++ строка - это просто указатель на память, где хранятся символы и с нулевым символом в конце. Если строки выглядят одинаково, они могут указывать на разные области памяти и не будут равными. чтобы проверить равенство, используйте класс C ++ std :: string или функцию C strcmp.

...