C++ сравнение строковых литералов
Я новичок в C++ (просто oldschool c). Мой сын попросил помочь с этим и я не могу это объяснить. Если бы он спросил меня: "как сравнить строки", Я бы сказал ему использовать strcmp (), но это не то, что меня смущает. Вот что он спросил:--4-->
int main()
{
cout << ("A"< "Z");
}
напечатает 1
int main()
{
cout << ("Z"< "A");
}
также будет печатать 1, но
int main()
{
cout << ("Z"< "A");
cout << ("A"< "Z");
}
будет печатать 10. Индивидуально оба оператора cout печатают 1, но выполняются подряд, я получаю другой ответ? 8 ответов
вы сравниваете адреса памяти. По-видимому, ваш компилятор помещает строковые литералы в память в том порядке, в котором он их встречает, поэтому первый "меньше", чем второй.
поскольку в первом фрагменте он видит" A "первым и" Z "вторым," A " меньше. Поскольку он видит "Z" первым во втором, "Z" меньше. В последнем фрагменте он уже имеет литералы "A" и "Z", размещенные при выполнении второй команды.
строковые литералы имеют статическую длительность хранения. Во всех этих сравнениях сравниваются адреса памяти, выделенные компилятором для строковых литералов. Похоже, что первый строковый литерал, с которым сталкивается компилятор, хранится в памяти с более низким адресом по сравнению со следующим встреченным строковым литералом.
таким образом в этой программе
int main()
{
cout << ("Z"< "A");
cout << ("A"< "Z");
}
строковый литерал "Z" был alllocated с более низким адресом, чем строковый литерал "A", потому что он был найден сначала компилятором.
учесть, что сравнения
cout << ("A"< "A");
может давать разные результаты в зависимости от параметров компилятора, поскольку компилятор может либо выделить два экстента памяти для строковых литералов, либо использовать только одну копию строковых литералов, которые являются одинаковыми.
из стандарта C++ (2.14.5 строковые литералы)
12 все ли строковые литералы различны (то есть хранятся в неперекрывающийся объекты) определяется реализация. Влияние попытка изменить строковый литерал не определена.
то же самое справедливо для C.
в заявлении:
cout << ("A"< "Z");
вы создали 2 строковые литералы: "A"
и "Z"
. Это типа const char *
который является указателем на массив символов с нулевым завершением. Сравнение здесь заключается в сравнении указателей, а не значений, на которые они указывают. Это сравнение адресов памяти, что дает вам предупреждение компилятора. Результат сравнения будет определяться тем, где компилятор выделил память для который будет несколько произвольным от компилятора к компилятору. В этом случае похоже, что первый найденный литерал получает первый адрес памяти вашим компилятором.
как и в C, чтобы правильно сравнить эти строковые литералы, вам нужно использовать strcmp
что будет делать сравнения стоимости.
однако, когда вы делаете что-то более идиоматичный способ c++, делая:
cout << (std::string("A") < std::string("Z"));
затем вы получаете правильное сравнение значений как этот оператор сравнения определен для std::string
.
Если вы хотите сравнить фактические строки c++, вам нужно объявить строки c++:
int main()
{
const std::string a("A");
const std::string z("Z");
cout << (z < a) << endl; // false
cout << (a < z) << endl; // true
}
в C++ результаты не указаны. Я буду использовать N3337 для C++11.
во-первых, мы должны посмотреть, что такое тип строкового литерала.
§2.14.5
9
обычные строковые литералы и строковые литералы UTF-8 также называется узкими строковыми литералами. Узкий строковый литерал имеет тип "массив nconst char
", где n размер строки как определено ниже, и имеет статическую длительность хранения (3.7).
массивы в разговорном языке говорят распад указатели.
§4.2
1
lvalue или rvalue типа " массивN T
" или "массив неизвестного границаT
"можно преобразовать в prvalue типа" указатель наT
". Результатом является указатель на первый элемент массива.
поскольку строковые литералы содержат один символ, они одного типа (char[2]
, включая символ null.)
поэтому применяется следующий абзац:
§5.9
2
[...]указатели на объекты или функции одного типа (после указателя преобразования) можно сравнить с результатом, определенным следующим образом:
[...]
- если два указателя
p
иq
одного и того же типа указывают на разные объекты, не являющиеся членами одного и того же объекта или элементов тот же массив или для разных функций, или если только одна из них равна null, результатыp<q
,p>q
,p<=q
иp>=q
не определен.
Unspecified означает, что поведение зависит от реализации. Мы видим, что GCC дает предупреждение об этом:
warning: comparison with string literal results in unspecified behaviour [-Waddress]
std::cout << ("Z" < "A");
поведение мая изменение между компиляторами или настройками компилятора, но в практика за то, что происходит, видеть Wintermute это ответ.
вы сравниваете адреса памяти. В следующем примере объясняется, как сравнить 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;
}
строковые константы ("A "и" Z") в C++ представлены понятием c - массивом символов, где последний символ "\0". Такие константы должны сравниваться с типом функции strcmp ().
Если вы хотите использовать сравнение c++ std::string, вы должны явно указать его:
cout << (std::string( "A") < "Z");
строка представляет указатель на область памяти. Таким образом, вы сначала сравниваете только адреса памяти с таким кодом
"Z"< "A"
сравнение строк выполняется с помощью функций. Они зависят от того," какая у вас струна". У вас есть строки массива символов, но они также являются объектами. Эти объекты имеют другие функции сравнения. Например, CString в MFC имеет функцию Compare, но также функцию CompareNoCase.
для ваших строк лучше всего использовать strcmp. Если вы debug и step in вы видите, что делает функция: она сравнивает каждый символ обеих строк и возвращает целое число, если происходит первая разница или ноль, если то же самое.
int result = strcmp("Z", "A");
здесь вы найдете еще несколько пример кода