Инициализация char* и std::string байтами

Определена ли следующая реализация:

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, поэтому мой вопрос:

Зависит ли вышеизложенное от компилятора?

char никогда не бывает того же типа, что и signed char, даже если char является подписанным типом.
eerorika 28.05.2019 20:14

строковые литералы const. Что вы имеете в виду под "я не могу сделать"?

463035818_is_not_a_number 28.05.2019 20:14

В чем вопрос? std::string = "\x96\xA0\xB4\xBE\xC8"; не компилируется

Thomas Sablik 28.05.2019 20:18

Хорошо, я изменил signed char на char, но char становится signed char в моем компиляторе.

user963241 28.05.2019 20:19

@user963241 user963241 что вы подразумеваете под «становится signed char в моем компиляторе»?

eerorika 28.05.2019 20:20
char может быть подписанным или беззнаковым, в любом случае это не тот же тип, что и signed char или unsigned char, это особенность языка, не пытайтесь понять его логику
463035818_is_not_a_number 28.05.2019 20:20

@user963241 user963241 Обратите внимание, что std::is_same_v<char, signed char> всегда ложно, даже если char подписано, поэтому вы не можете преобразовать char * в signed char *.

HolyBlackCat 28.05.2019 20:22

Как еще я должен сказать тогда? Я уверен, вы знаете, что char должно быть либо signed char, либо unsigned char :)

user963241 28.05.2019 20:22

нет, char либо без знака, либо со знаком, но ни usigned char, ни signed char :P

463035818_is_not_a_number 28.05.2019 20:23

Нет. char должен быть либо подписанным, либо беззнаковым, но это всегда другой тип по сравнению с signed char и unsigned char.

HolyBlackCat 28.05.2019 20:23

Кроме того, вы должны использовать constchar *cp, иначе преобразование строковых литералов в него будет неправильным (я думаю, начиная с C++11).

HolyBlackCat 28.05.2019 20:25

я позволил себе отредактировать вопрос, чтобы действительно задать вопрос. Просто откатитесь, если вам не нравится

463035818_is_not_a_number 28.05.2019 20:27

В C и C++ есть типы 3char; char, signed char и unsigned char. Все они различные типы (даже если два из них могут иметь перекрывающиеся диапазоны на разных платформах). Однажды меня это укусило, так как char в AiX (с xlc) и char в Linux (с gcc) не имеют одинаковой подписи.

Jesper Juhl 28.05.2019 20:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
13
120
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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 28.05.2019 20:25

@ user963241 это не помогает сделать значение строкового литерала независимым от компилятора. Вместо этого вы можете использовать массив, как показано в моем редактировании.

eerorika 28.05.2019 20:32

Да, я имею в виду, что подписанность определяется реализацией, а также тем, как значение, например. '\ x96' также определяется реализацией, но если мы делаем unsigned char c = '\x96', то это правильно определено.

user963241 28.05.2019 20:33

@user963241 user963241 Да, к каждому утверждению. Хотя правильный синтаксис unsigned char c = 0x96;

eerorika 28.05.2019 20:34

Не существует компьютерной системы, в которой char меньше 8 бит или не является дополнением до двух. Похоже, C++20 наконец-то станет признать, что.

rustyx 28.05.2019 20:36

Итак, когда люди используют char *c с такой шестнадцатеричной строкой, разве они не делают свой код зависимым от компилятора? Должен ли я использовать unsigned char с такой шестнадцатеричной строкой?

user963241 28.05.2019 20:37

@ user963241 Да. Вам следует использовать массив unsigned char, а не строковый литерал, если вы хотите использовать значения больше 0x7F и не зависеть от реализации.

eerorika 28.05.2019 20:39

@rustyx «Не существует компьютерной системы, в которой char меньше 8 бит» - это просто не правда: stackoverflow.com/a/2215694/5910058 - редкость, да. Несуществующий, нет.

Jesper Juhl 28.05.2019 20:42

@rustyx любопытно, что они не предлагали сделать шестнадцатеричные escape-последовательности за пределами диапазона char четко определенными, что, я полагаю, они могли бы предложить, учитывая, что дополнение до 2 гарантировано. По крайней мере, ни в связанном предложении, ни в последнем черновике этого нет.

eerorika 28.05.2019 20:43

Кажется, это невозможно сделать с помощью std::string, то есть быть независимым от реализации, верно? потому что он не будет использовать unsigned char?

user963241 28.05.2019 20:45

@user963241 user963241 Я не уверен на 100% в std::string. Возможно, в С++ 20 с гарантией дополнения до 2. В этом случае значения могут быть в другом диапазоне, чем вы ожидаете. std::basic_string<unsigned char> это точно; Я добавил пример.

eerorika 28.05.2019 20:56

Другие вопросы по теме