Вопрос

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

#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?Что, если я использую квалификатор const?Решение состоит в том, чтобы использовать std::string?

Это было полезно?

Решение

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

if (option == "foo")

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

Другие советы

Вы можете использовать == оператор для сравнения строк, только если вы используете 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) 
   ...

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

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

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

Ренце

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top