简体   繁体   English

字符串字面量的 C++ 比较

[英]C++ Comparison of String Literals

I'm a c++ newbie (just oldschool c).我是一个 C++ 新手(只是 oldschool c)。 My son asked for help with this and I'm unable to explain it.我儿子为此寻求帮助,我无法解释。 If he had asked me "how do I compare strings" I would have told him to use strcmp(), but that isn't what is confusing me.如果他问我“我如何比较字符串”,我会告诉他使用 strcmp(),但这并不是让我感到困惑的地方。 Here is what he asked:这是他问的:

int main() 
{ 
  cout << ("A"< "Z");
}

will print 1将打印 1

int main() 
{ 
  cout << ("Z"< "A");
}

will also print 1, but也会打印 1,但是

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}

will then print 10. Individually both cout statements print 1, but executed in a row I get a different answer?然后将打印 10。单独两个 cout 语句打印 1,但连续执行我得到不同的答案?

You are comparing memory addresses.您正在比较内存地址。 Apparently your compiler places the string literals in memory in the order it encounters them, so the first is "lesser" than the second.显然,您的编译器将字符串文字按照遇到它们的顺序放置在内存中,因此第一个比第二个“小”。

Since in the first snippet it sees "A" first and "Z" second, "A" is lesser.由于在第一个片段中它首先看到“A”,然后看到“Z”,因此“A”较小。 Since it sees "Z" first in the second, "Z" is lesser.由于它在第二个中首先看到“Z”,因此“Z”较小。 In the last snippet, it already has literals "A" and "Z" placed when the second command rolls around.在最后一个片段中,当第二个命令出现时,它已经放置了文字“A”和“Z”。

String literals have static storage duration.字符串文字具有静态存储持续时间。 In all these comparisons there are compared addresses of memory allocated by the compiler for string literals.在所有这些比较中,都有编译器为字符串文字分配的内存的比较地址。 It seems that the first string literal that is encountered by the compiler is stored in memory with a lower address compared with the next encountered string literal.与下一个遇到的字符串文字相比,编译器遇到的第一个字符串文字似乎以较低的地址存储在内存中。

Thus in this program因此在这个程序中

int main() 
{ 
  cout << ("Z"< "A");
  cout << ("A"< "Z");
}

string literal "Z" was alllocated with a lower address than string literal "A" because it was found first by the compiler.字符串文字“Z”分配的地址低于字符串文字“A”,因为它首先被编译器找到。

Take into account that comparison考虑到这种比较

  cout << ("A"< "A");

can give different results depending on the options of the compiler because the compiler may either allocate two extents of memory for the string literals or use only one copy of the string literals that are the same.可以根据编译器的选项给出不同的结果,因为编译器可能会为字符串文字分配两个内存区,或者只使用相同的字符串文字的一个副本。

From the C++ Standard (2.14.5 String literals)来自 C++ 标准(2.14.5 字符串文字)

12 Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation defined. 12 是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。 The effect of attempting to modify a string literal is undefined.尝试修改字符串文字的效果是未定义的。

The same is valid for C.这同样适用于 C。

In the statement:在声明中:

cout << ("A"< "Z");

You have created 2 string literals : "A" and "Z" .您已经创建了 2 个字符串文字"A""Z" These are of type const char * which is a pointer to a null terminated array of characters.这些是const char *类型,它是一个指向空终止字符数组的指针。 The comparison here is comparing the pointers and not the values that they point to.这里的比较是比较指针而不是它们指向的值。 It's this comparing of memory addresses here which is what gives you the compiler warning.正是这种内存地址的比较在这里为您提供了编译器警告。 The result of the comparison is going to be determined by where the compiler allocated the memory to which is going to be somewhat arbitrary from compiler to compiler.比较的结果将取决于编译器分配内存的位置,从编译器到编译器将有点随意。 In this case it looks like the first literal found is getting assigned the first memory address by your compiler.在这种情况下,您的编译器似乎为找到的第一个文字分配了第一个内存地址。

Just like in C to compare these string literals properly you need to use strcmp which will do a value comparison.就像在 C 中正确比较这些字符串文字一样,您需要使用strcmp来进行值比较。

However when you do something the more idiomatic c++ way by doing:但是,当您通过以下方式以更惯用的 C++ 方式执行某些操作时:

cout << (std::string("A") < std::string("Z"));

Then you get the proper comparison of the values as that comparison operator is defined for std::string .然后您会得到正确的值比较,因为该比较运算符是为std::string定义的。

If you want to compare actual C++ strings, you need to declare C++ strings:如果要比较实际的 C++ 字符串,则需要声明 C++ 字符串:

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

  cout << (z < a) << endl; // false
  cout << (a < z) << endl; // true
}

In C++, the results are unspecified.在 C++ 中,结果是未指定的。 I will be using N3337 for C++11.我将在 C++11 中使用N3337

First, we have to look at what the type of a string literal is.首先,我们必须看看字符串文字的类型是什么。

§2.14.5 §2.14.5

9 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. 9普通字符串文字和 UTF-8 字符串文字也称为窄字符串文字。 A narrow string literal has type "array of n const char ", where n is the size of the string as defined below, and has static storage duration (3.7).窄字符串文字的类型为“ n const char数组”,其中n是如下定义的字符串大小,并且具有静态存储持续时间 (3.7)。

Arrays are colloquially said to decay to pointers.通俗地说,数组会衰减为指针。

§4.2 §4.2

1 An lvalue or rvalue of type "array of NT " or "array of unknown bound of T " can be converted to a prvalue of type "pointer to T ". 1NT数组”或“ T的未知边界数组”类型的左值或右值可以转换为“指向T指针”类型的纯右值。 The result is a pointer to the first element of the array.结果是指向数组第一个元素的指针。

Since your string literals both contain one character, they're the same type ( char[2] , including the null character.)由于您的字符串文字都包含一个字符,因此它们的类型相同( char[2] ,包括空字符。)

Therefore the following paragraph applies:因此,以下段落适用:

§5.9 §5.9

2 [...] 2 [...]

Pointers to objects or functions of the same type (after pointer conversions) can be compared, with a result defined as follows:可以比较指向相同类型(指针转换后)的对象或函数的指针,结果定义如下:

[...] [...]

— If two pointers p and q of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them is null, the results of p<q , p>q , p<=q , and p>=q are unspecified. — 如果两个相同类型的指针pq指向不同的对象,这些对象不是同一对象的成员或同一数组的元素或不同的函数,或者如果其中只有一个为空,则p<q的结果, p>qp<=qp>=q未指定。

Unspecified means that the behavior depends on the implementation.未指定意味着行为取决于实现。 We can see that GCC gives a warning about this:我们可以看到 GCC 对此给出了警告:

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

The behavior may change across compilers or compiler settings but in practice for what happens, see Wintermute's answer .行为可能会因编译器或编译器设置而异,但在实践中会发生什么,请参阅 Wintermute 的回答

You are comparing memory addresses.您正在比较内存地址。 The example that follow explains how to compare 2 strings:以下示例说明了如何比较 2 个字符串:

#include "stdafx.h"
#include <iostream>
#include <cstring> //prototype for strcmp()

int _tmain(int argc, _TCHAR* argv[])
{
 using namespace std;

 cout << strcmp("A", "Z"); // will print -1
 cout << strcmp("Z", "A"); // will print 1

 return 0;
}

The string constants ("A" and "Z") in C++ are represented by the C concept - array of characters where the last character is '\\0'. C++ 中的字符串常量(“A”和“Z”)由 C 概念表示 - 字符数组,其中最后一个字符是 '\\0'。 Such constants have to be compared with strcmp() type of function.此类常量必须与 strcmp() 类型的函数进行比较。

If you would like to use the C++ std::string comparison you have to explicitly state it:如果您想使用 C++ std::string 比较,您必须明确说明它:

cout << (std::string( "A") < "Z");

A String is representing a pointer to memory area.字符串表示指向内存区域的指针。 So you at first compare only memory addresses with such code因此,您首先仅将内存地址与此类代码进行比较

"Z"< "A"

comparing strings is done with functions.比较字符串是用函数完成的。 They depend on "what kind of string" you have.它们取决于您拥有“什么样的字符串”。 You have char array strings, but they mid also be objects.您有字符数组字符串,但它们中间也是对象。 These objects have other comparision functions.这些对象具有其他比较功能。 For instance the CString in MFC has the Compare but also the CompareNoCase function.例如,MFC 中的 CString 具有 Compare 和 CompareNoCase 函数。

For your strings you best use the strcmp.对于您的字符串,您最好使用 strcmp。 If you debug and step in you see what the function does: it compares every char of both strings and return an integer if the first difference occurs or zero if the same.如果您调试并介入,您会看到该函数的作用:它比较两个字符串的每个字符,如果出现第一个差异则返回一个整数,如果相同则返回零。

int result = strcmp("Z", "A");

Here you find some further sample code在这里您可以找到一些进一步的示例代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM