字符串字面值的比较

5
这是非常简单的代码:
#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[]

to

char *opt

程序可以正常运行,但为什么会生成警告?这与\0终止有关吗?opt的两个声明之间有什么区别?如果我使用const限定符会怎样?解决方案是使用std::string。


2
一份重复的问题:http://stackoverflow.com/questions/1997778/c-comparing-c-string-problem - Georg Fritzsche
当你执行 if (option == "foo") 时,你并不是在比较两个字符串 -- 你正在比较两个 指针 - John Dibling
4个回答

18

在C++中,字符数组或字符指针并不完全等同于字符串类对象,因此这个问题

if (option == "foo")

这段代码并没有比较字符串option和字符串"foo"本身的内容,而是比较了option指针的地址和字符串"foo"字面值的地址。如果你想判断


2
它“工作”并不是因为你将其声明为char*,而是因为你将其赋值为指向字符串文字“foo”的指针。然后,当你稍后将其与文字“foo”进行比较时,如果编译器已经合并了这两个“foo”,那么地址将是相同的。编译器通常会认识到你在两个地方使用了相同的字符串文字,并使它们都引用同一个文字,但这在一般情况下不起作用。 - John Knoeller
如果从John的评论中不够清楚,char x[] = "..." 在内存中创建了一个连续的char块并复制了内容,而char * x ="..."则创建了一个单一的指针并分配了字面量的地址。 - David Rodríguez - dribeas

5

如果你使用std::string(这是一个好习惯),你可以使用==运算符来比较字符串。但如果你使用C风格的char*/char[]字符串,则需要使用C函数strcmpstrncmp

你也可以使用std::string::operator ==来比较std::string和C字符串:

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

if (foo == bar) 
   ...

如果我不想使用C包含文件,而是将char*作为函数参数,那么这样做是否好呢?可以这样写:if(std::string(option) == std::string("foo"))。 - Ruggero Turra
如果 (std::string(option) == "foo") 可以工作,我已经编辑了答案。 - Laurynas Biveinis
@wiso:为什么你想使用char*而不是string,但又不包含cstring函数? - Mark B
你说得对。一般来说,我不喜欢在C++中使用C库,所以我会转换为std::string。我想在参数中使用char*,以保持函数签名不变。 - Ruggero Turra

3
它无法工作的原因是因为比较不是针对字符串进行的,而是字符指针。

当使用char*时,它可能会工作的原因是编译器可能会决定只存储一次字面字符串"opt"并将其重用于两个引用(我确定在某个地方看到过编译器设置来指示编译器是否这样做)。

在char opt[]的情况下,编译器将字符串字面值复制到为opt数组保留的存储区域中(可能在堆栈上),这导致指针不同。

Renze


2

对于 C++,我会使用 std::string solution

#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*等创建自己,因此您仍然可以以这些方式调用该函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接