字符串文字的C++比较

sim*_*sid 62 c++ string-literals

我是一个c ++新手(只是oldschool c).我的儿子请求帮助,我无法解释.如果他问我"我如何比较字符串"我会告诉他使用strcmp(),但这并不是让我感到困惑的原因.以下是他的问题:

int main() 
{ 
  cout << ("A"< "Z");
}
Run Code Online (Sandbox Code Playgroud)

将打印1

int main() 
{ 
  cout << ("Z"< "A");
}
Run Code Online (Sandbox Code Playgroud)

也会打印1,但是

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}
Run Code Online (Sandbox Code Playgroud)

然后将打印10.单独两个cout语句打印1,但连续执行我得到一个不同的答案?

Win*_*ute 88

您正在比较内存地址.显然,您的编译器会按照遇到它们的顺序将字符串文字放在内存中,因此第一个字符串比第二个字符串"小".

因为在第一个片段中它首先看到"A"而第二个看到"Z",所以"A"较小.由于它在第二个中首先看到"Z",所以"Z"较小.在最后一个片段中,当第二个命令滚动时,它已经放置了文字"A"和"Z".

  • 我认为值得注意的是,这与"oldschool c"中的情况完全相同. (24认同)
  • @Roland Nope,至少在C++ 11中没有说明.§5.9/ 2"如果同一类型的两个指针p和q指向不是同一个对象的成员的不同对象或同一个数组的元素或不同的函数,或者只有其中一个为null,则结果为p <q,p> q,p <= q,p> = q未指定" (2认同)

Vla*_*cow 21

字符串文字具有静态存储持续时间.在所有这些比较中,比较了编译器为字符串文字分配的内存地址.看起来编译器遇到的第一个字符串文字存储在内存中,与下一个遇到的字符串文字相比,地址较低.

因此在这个计划中

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}
Run Code Online (Sandbox Code Playgroud)

字符串文字"Z"的字母低于字符串文字"A",因为它首先由编译器找到.

考虑到这种比较

  cout << ("A"< "A");
Run Code Online (Sandbox Code Playgroud)

根据编译器的选项可以给出不同的结果,因为编译器可以为字符串文字分配两个内存范围,或者只使用相同字符串文字的一个副本.

来自C++标准(2.14.5字符串文字)

12是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的.尝试修改字符串文字的效果是未定义的.

这同样适用于C.

  • 值得注意的是,这些不是C++`std :: string`类型的字符串,而是`char*`C风格的字符串. (4认同)

shu*_*e87 14

在声明中:

cout << ("A"< "Z");
Run Code Online (Sandbox Code Playgroud)

您创建了2个字符串文字:"A""Z".这些类型const char *是指向以null结尾的字符数组的指针.这里的比较是比较指针而不是它们指向的值.这是内存地址的比较,这是给你编译器警告的原因.比较的结果将取决于编译器从编译器到编译器分配内存的位置.在这种情况下,看起来第一个文字被编译器分配了第一个内存地址.

就像在C中正确比较这些字符串文字一样,您需要使用strcmp哪个将进行值比较.

但是当你做一些更惯用的c ++方式:

cout << (std::string("A") < std::string("Z"));
Run Code Online (Sandbox Code Playgroud)

然后,在定义比较运算符时,您可以正确比较值std::string.


tad*_*man 7

如果要比较实际的C++字符串,则需要声明C++字符串:

int main() 
{
  const std::string a("A");
  const std::string z("Z");

  cout << (z < a) << endl; // false
  cout << (a < z) << endl; // true
}
Run Code Online (Sandbox Code Playgroud)


小智 7

在C++中,结果未指定.我将使用N3337 for C++ 11.

首先,我们必须查看字符串文字的类型.

§2.14.5

9普通字符串文字和UTF-8字符串文字也称为窄字符串文字.窄字符串文字的类型为" n的 数组const char",其中n是下面定义的字符串的大小,并且具有静态存储持续时间(3.7).

通俗地说,数组会衰减到指针.

4.2节

1可以将"数组N T"或"未知范围的数组" 类型的左值或右值T转换为"指向T" 的类型的prvalue .结果是指向数组的第一个元素的指针.

由于您的字符串文字都包含一个字符,因此它们是相同的类型(char[2]包括空字符).

因此,以下段落适用:

§5.9

2 [...]

可以比较指向相同类型的对象或函数的指针(在指针转换之后),结果定义如下:

[...]

-如果两个指针pq相同类型的点不属于相同对象的成员或相同数组的元素或不同的功能,或者如果只有它们中的一个为空,结果不同的对象p<q,p>q,p<=q,和p>=q是未指定的.

未指定意味着行为取决于实现.我们可以看到GCC对此发出警告:

warning: comparison with string literal results in unspecified behaviour [-Waddress]
     std::cout << ("Z" < "A");
Run Code Online (Sandbox Code Playgroud)

行为可能会在编译器或编译器设置中发生变化,但在实践中会发生变化,请参阅Wintermute的答案.