Определена ли следующая реализация:
char *cp = "\x96\xA0\xB4\xBE\xC8";
а также:
std::string = "\x96\xA0\xB4\xBE\xC8";
char
означает signed char
в моем компиляторе (MSVC 2015).
Я понял, что я не могу сделать следующее:
unsigned char *cp = "\x96\xA0\xB4\xBE\xC8";
"\x96\xA0\xB4\xBE\xC8"
- это байты в диапазоне от 0 до 255, поэтому мой вопрос:
Зависит ли вышеизложенное от компилятора?
строковые литералы const
. Что вы имеете в виду под "я не могу сделать"?
В чем вопрос? std::string = "\x96\xA0\xB4\xBE\xC8";
не компилируется
Хорошо, я изменил signed char
на char
, но char
становится signed char
в моем компиляторе.
@user963241 user963241 что вы подразумеваете под «становится signed char
в моем компиляторе»?
char
может быть подписанным или беззнаковым, в любом случае это не тот же тип, что и signed char
или unsigned char
, это особенность языка, не пытайтесь понять его логику
@user963241 user963241 Обратите внимание, что std::is_same_v<char, signed char>
всегда ложно, даже если char
подписано, поэтому вы не можете преобразовать char *
в signed char *
.
Как еще я должен сказать тогда? Я уверен, вы знаете, что char
должно быть либо signed char
, либо unsigned char
:)
нет, char
либо без знака, либо со знаком, но ни usigned char
, ни signed char
:P
Нет. char
должен быть либо подписанным, либо беззнаковым, но это всегда другой тип по сравнению с signed char
и unsigned char
.
Кроме того, вы должны использовать const
char *cp
, иначе преобразование строковых литералов в него будет неправильным (я думаю, начиная с C++11).
я позволил себе отредактировать вопрос, чтобы действительно задать вопрос. Просто откатитесь, если вам не нравится
В C и C++ есть типы 3char
; char
, signed char
и unsigned char
. Все они различные типы (даже если два из них могут иметь перекрывающиеся диапазоны на разных платформах). Однажды меня это укусило, так как char
в AiX (с xlc) и char
в Linux (с gcc) не имеют одинаковой подписи.
Is the following implementation-defined:
signed char *cp = "\x96\xA0\xB4\xBE\xC8";
and as well as:
std::string = "\x96\xA0\xB4\xBE\xC8";
В системах с 8-битным знаком char
да. Шестнадцатеричная escape-последовательность в узком строковом литерале имеет значение, определяемое реализацией, если оно выходит за пределы диапазона, определенного реализацией, определенного для char
. Предполагая 8-битный знак char
, любое шестнадцатеричное значение больше 7F
выходит за пределы диапазона представляемых значений.
В этом отношении не имеет значения, используется ли этот литерал для инициализации std::string
или указателя на символ.
Вы можете использовать массив unsigned char
вместо строкового литерала:
static constexpr unsigned char cp[] = {
0x96,
0xA0,
0xB4,
0xC8,
};
Вы можете использовать этот массив для инициализации std::basic_string<unsigned char>
, если вам это нужно:
std::basic_string<unsigned char> s = {std::begin(cp), std::end(cp)};
P.S. Преобразование из строкового литерала в неконстантный указатель char является некорректным (начиная с C++11; ранее преобразование было корректным, но устарело).
P.P.S char
, unsigned char
и signed char
всегда являются тремя разными типами, независимо от того, подписан char
или нет.
Можно ли сделать это четко определенным и не зависящим от компилятора? Например. У меня не получилось: unsigned char *cp = "\x96\xA0\xB4\xBE\xC8";
это надо?
@ user963241 это не помогает сделать значение строкового литерала независимым от компилятора. Вместо этого вы можете использовать массив, как показано в моем редактировании.
Да, я имею в виду, что подписанность определяется реализацией, а также тем, как значение, например. '\ x96' также определяется реализацией, но если мы делаем unsigned char c = '\x96'
, то это правильно определено.
@user963241 user963241 Да, к каждому утверждению. Хотя правильный синтаксис unsigned char c = 0x96
;
Не существует компьютерной системы, в которой char
меньше 8 бит или не является дополнением до двух. Похоже, C++20 наконец-то станет признать, что.
Итак, когда люди используют char *c
с такой шестнадцатеричной строкой, разве они не делают свой код зависимым от компилятора? Должен ли я использовать unsigned char
с такой шестнадцатеричной строкой?
@ user963241 Да. Вам следует использовать массив unsigned char
, а не строковый литерал, если вы хотите использовать значения больше 0x7F и не зависеть от реализации.
@rustyx «Не существует компьютерной системы, в которой char меньше 8 бит» - это просто не правда: stackoverflow.com/a/2215694/5910058 - редкость, да. Несуществующий, нет.
@rustyx любопытно, что они не предлагали сделать шестнадцатеричные escape-последовательности за пределами диапазона char
четко определенными, что, я полагаю, они могли бы предложить, учитывая, что дополнение до 2 гарантировано. По крайней мере, ни в связанном предложении, ни в последнем черновике этого нет.
Кажется, это невозможно сделать с помощью std::string
, то есть быть независимым от реализации, верно? потому что он не будет использовать unsigned char
?
@user963241 user963241 Я не уверен на 100% в std::string
. Возможно, в С++ 20 с гарантией дополнения до 2. В этом случае значения могут быть в другом диапазоне, чем вы ожидаете. std::basic_string<unsigned char>
это точно; Я добавил пример.
char
никогда не бывает того же типа, что иsigned char
, даже еслиchar
является подписанным типом.