Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.95/120: Рейтинг темы: голосов - 120, средняя оценка - 4.95
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700

Что из себя представляет std::wstring?

05.06.2017, 17:58. Показов 26164. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В общем насколько я понимаю это string с типом wchar_t.

Но есть вопросы:
1. Размер типа wchar_t зависит от компилятора и не стандартизирован(кто и как с этим борется?)
2. В чем вообще профит от wchar_t если char позволяет хранить любые данные?
Сначала подумал что методы ведут себя по другому в отличии от обычного string и соответственно wchar_t, но тесты показали иной результат.

Код ниже выводит размер строки как 5 байт
C++
1
2
3
4
5
6
7
8
9
10
//g++  5.4.0
 
#include <iostream>
#include <string>
 
int main()
{
    std::wstring s = L"hello";
    std::cout << s.length() << " size: " << sizeof(wchar_t);
}
http://rextester.com/ZOZS97901

Но в данной реализации размер wchar_t равен 4 байта, а это означает что потребуется как минимум 2 wchar_t что бы сохранить эти 5 байт в данной реализации, а это уже 8 байт. Но результат s.length() выдаёт 5. Почему так происходит? По поведению wstring в данном случае ничем не отличается от обычного string, ещё и L приходится добавлять(кстати, зачем добавлять L)?

Не понятно зачем нужен wstring, прошу обьяснить что к чему
1
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.06.2017, 17:58
Ответы с готовыми решениями:

Union что из себя представляет?
Читал много книг и там про него не чего не было сказано, парни объясните мне пожалуйста для чего он?

Что из себя представляет допустим поток ввода/вывода
Поясните пожалуйста что из себя представляет допустим поток ввода/вывода в С++ ? Это участок памяти который представляет собой что-то вроде...

Что из себя представляет код в стеке, и как его использовать
Гугл мне по этому поводу не помог, поэтому спрашиваю тут: что из себя представляет из себя код в стеке, как его использовать(вызвать там и...

23
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
05.06.2017, 18:17
Цитата Сообщение от Undisputed Посмотреть сообщение
. В чем вообще профит от wchar_t если char позволяет хранить любые данные?
Не любые: 0 - 255.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 18:18  [ТС]
nd2,
Я имел ввиду string где типом символов является char - тогда нормально все работает.

По поводу буквы L предполагаю что wchar_t объявлен как числовой тип, поэтому строковый литерал нужно приводить к числу, что и делает буква L в данном случае(long). Я прав по этому поводу?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
05.06.2017, 18:39
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Цитата Сообщение от Undisputed Посмотреть сообщение
Но результат s.length() выдаёт 5. Почему так происходит?
length() выдает количество элементов типа wchar_t в wstring. В данном случае их 5 (каждый по 4 байта).

Цитата Сообщение от Undisputed Посмотреть сообщение
В чем вообще профит от wchar_t если char позволяет хранить любые данные?
Для хранения юникода. В массиве char тоже можно хранить юникод (в utf-8), но это не всегда подходит. Например для windows нативным юникодом является utf-16, который как раз может храниться в wstring, в string его не запихнуть.

Цитата Сообщение от Undisputed Посмотреть сообщение
Размер типа wchar_t зависит от компилятора и не стандартизирован(кто и как с этим борется?)
http://en.cppreference.com/w/c... ng_literal

Добавлено через 8 минут
Цитата Сообщение от Undisputed Посмотреть сообщение
По поводу буквы L предполагаю что wchar_t объявлен как числовой тип, поэтому строковый литерал нужно приводить к числу, что и делает буква L в данном случае(long). Я прав по этому поводу?
wchar_t, как и char, - интегральный тип.

Что касается L:
2.13.3-2.13.5
A string-literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type
“array of n const wchar_t”
, where n is the size of the string as defined below; it is initialized with the given
characters.
A character literal that does not begin with u8, u, U, or L is an ordinary character literal. An ordinary
character literal that contains a single c-char representable in the execution character set has type char,
with value equal to the numerical value of the encoding of the c-char in the execution character set. An
ordinary character literal that contains more than one c-char is a multicharacter literal. A multicharacter
literal, or an ordinary character literal containing a single c-char not representable in the execution character
set, is conditionally-supported, has type int, and has an implementation-defined value.
A character literal that begins with the letter L, such as L’z’, is a wide-character literal. A wide-character
literal has type wchar_t. The value of a wide-character literal containing a single c-char has value equal
to the numerical value of the encoding of the c-char in the execution wide-character set, unless the c-char
has no representation in the execution wide-character set, in which case the value is implementation-defined.
[ Note: The type wchar_t is able to represent all members of the execution wide-character set (see 3.9.1).
— end note ]. The value of a wide-character literal containing multiple c-chars is implementation-defined.
4
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 18:43  [ТС]
DrOffset,
В почему в string не запихнуть? Можно же оперируя строковыми литералами присвоить в string любой символ
Другое дело если вызывать push_back для многобайтового символа, тогда да, будут проблемы. Но тут тоже можно же решить через +=
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
05.06.2017, 18:46
Цитата Сообщение от Undisputed Посмотреть сообщение
В почему в string не запихнуть?
Потому что не все символы вкладываются в диапазон 0-255
Цитата Сообщение от Undisputed Посмотреть сообщение
Можно же оперируя строковыми литералами присвоить в string любой символ
Нет, не любой.
2
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
05.06.2017, 18:57
Цитата Сообщение от Undisputed Посмотреть сообщение
1. Размер типа wchar_t зависит от компилятора и не стандартизирован(кто и как с этим борется?)
"Борются" используя char16_t. В кавычках потому что, скажем, версии std::to_string поддерживающей std::basic_string<char16_t> строки нет.
Цитата Сообщение от Undisputed Посмотреть сообщение
В почему в string не запихнуть? Можно же оперируя строковыми литералами присвоить в string любой символ
Потому что один символ 心 будет занимать несколько восьмибитовых char с utf8. И плясать с бубном вокруг переменного числа чаров на символ никому не интересно.
2
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
05.06.2017, 19:04
Цитата Сообщение от Undisputed Посмотреть сообщение
В почему в string не запихнуть?
Я имел в виду не запихнешь в естественном виде. Как бинарный blob данных, да, пожалуйста, но это уже не будет строкой. Строго говоря, строки (классы string и wstring) в С++ - это не совсем строки, т.к. они не вводят абстракции символа. Это относительно тонкие обертки над соответствующими массивами. Если у тебя в std::string лежит utf-8 - ты никак не сможешь проиндексировать символ, более того, в std::wstring utf-16 ты тоже в общем случае не сможешь его проиндексировать, т.к. в utf-16 на символ может приходиться до двух 16-битных слов (т.н. суррогатные пары). И только в случае, когда у нас wchar_t -32 бита и мы храним utf-32 - абстракция элемента string будет совпадать с символом.

А вообще давай ты сейчас сперва почитаешь о трех вещах (можно на википедии):
* Про UTF-16.
* Про UTF-8.
* Про порядок байтов.
3
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 19:27  [ТС]
MrGluck,
Вот пример, где при помощи строкового литерала в string добавляется Китайский иероглиф. Стока по сути же набор байт, вот этот символ и вмещается в 3 char - а.

C++
1
2
3
4
5
6
7
#include <iostream>
 
int main()
{
    std::string s = "不";
    std::cout << s.length();
}
http://rextester.com/UXAGK72894

Или тут речь именно о том случае, когда приходится оперировать отдельными символами без использования строкового литерала?

DrOffset,
Я понял о чем ты) значит все таки суть в том что бы корректно оперировать отдельными символами. Но в UTF-8 размер символа вроде не фиксированный, зависит от символа и может быть равен насколько я знаю от 1 до 4 байт, а wchar имеет фиксированный размер. Как в таком случае оперировать отдельными символами если размер символов не фиксированный а wchar фиксированный? В UTF-8 строке же могут быть разные символы, как однобайтовые так и трехбайтовые
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
05.06.2017, 19:41
Строки работают с английским, но не с кирилицей
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
05.06.2017, 19:43
Цитата Сообщение от Undisputed Посмотреть сообщение
Но в UTF-8 размер символа вроде не фиксированный, зависит от символа и может быть равен насколько я знаю от 1 до 4 байт, а wchar имеет фиксированный размер.
Фиксированный размер только для wchar_t == 32 бита или для UCS-2. Почитай про представление юникода (1 и 2), и нам тебе проще объяснять будет после этого и вопросы многие отпадут.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 20:09  [ТС]
DrOffset,
Ну я вроде как понимаю представление юникода
Просто вот чего не пойму, символ "а" равен одному байту в utf-8, а wchar это может быть например 4 байта
заполнений нулями после символа "а" в utf-8 не предусмотрено, а значит используя wchar мы теряем три байта памяти, плюс ввиду того что внутри wchar оставшиеся 3 байта будут нулями, то мы не только тратим лишнюю память, но ещё и можем получить совсем другой символ при выводе его на экран. думаю сравнивать такой символ с переменной типа wchar можно без проблем, но что если я например передаю эти данные например по сети, однобайтовый символ уйдёт на сервер как 4 байта, т.к wchar в данном случае равен 4 байта, и запрос будет соответственно некорректным с точки зрения данных, разве нет ?

Добавлено через 1 минуту
То есть планировалась отправка однобайтового символа а отправилось четыре вместо одного

Добавлено через 6 минут
Или если подряд идут более одного нуля, то все дальнейшие нули не принимают участие в интерпретации символа?

Добавлено через 27 секунд
Запутался я что то....
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
05.06.2017, 20:14
Цитата Сообщение от Undisputed Посмотреть сообщение
заполнений нулями после символа "а" в utf-8 не предусмотрено, а значит используя wchar мы теряем три байта памяти
Стандартная вилка - или память, или скорость. А чтоб и данные лежали компактно как в utf-8, и работать с ними было также удобно как с wchar_t, так не бывает.
И вообще, в наш век гигабайтных планок памяти, экономить на размерах символов - чистое крохоборство.
Цитата Сообщение от Undisputed Посмотреть сообщение
но что если я например передаю эти данные например по сети
То выясняется что HTTP сто лет как умеет сжимать поток данных gzip-ом ("HTTP compression" называется).
Цитата Сообщение от Undisputed Посмотреть сообщение
и запрос будет соответственно некорректным с точки зрения данных, разве нет ?
Будет корректным, если заранее договоритесь о формате в котором данные передаются. И да, HTTP определяет конец передаваемых данных совсем не по нолику в конце. В самом дубовом варианте концом данных считается "а вот тут абонент повесил трубку" (закрыл сокет).
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 20:40  [ТС]
Renji,
А там дело не только в памяти, когда в wchar кладётся однобайтовый символ, то представление этого символа изменяется т.к у нас уже не один байт а четыре, в итоге мы теряем связь с данными. Так же тут ещё будет ощутима проблема с пропускной способностью сети, если данных много и скорость связи критична.

Что касается сетевых вопросов, то там HTTP может и не быть, и gzip-а соответственно.
Закрыл сокет - это уже TCP левел хттп \r\n два раза

И ещё, договориться не всегда получается, может я на гугл передаю данные, не буду же я им договоры присылать, а они послушно реализовывать, если конечно моё предложение не будет им очень интересно

В общем как я понял широкий символ с юникодом никак не связан, он нужен просто для оперирования некоторыми данными где каждое количество фиксированных байт представляет собой какой то особый интерес независимо от кодировки. Кто не согласен и почему ?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
05.06.2017, 20:51
Цитата Сообщение от Undisputed Посмотреть сообщение
А там дело не только в памяти, когда в wchar кладётся однобайтовый символ, то представление этого символа изменяется т.к у нас уже не один байт а четыре, в итоге мы теряем связь с данными.
Ну так не надо устраивать кашу из кодировок. Храните все в UTF32 и перекладывать однобайтовые символы в wchar_t вам просто не понадобится.
Цитата Сообщение от Undisputed Посмотреть сообщение
И ещё, договориться не всегда получается, может я на гугл передаю данные, не буду же я им договоры присылать, а они послушно реализовывать
Все тот же HTTP позволяет явно указать кодировку данных. А кто мог, но не задал понадеявшись на русское авось - ССЗБ.
Цитата Сообщение от Undisputed Посмотреть сообщение
В общем как я понял широкий символ с юникодом никак не связан
Де-юре не связан. Де-факто очень маловероятно что кто-то будет класть в wchar_t что-то кроме юникода. Хотя, какие-то экзотические 16-битовые кодировки вроде бы в природе есть.
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
05.06.2017, 20:53
...
Миниатюры
Что из себя представляет std::wstring?  
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 21:00  [ТС]
Renji,
Дело в том что каши нет Символы в ютф-8 имеют различную длину, от 1 байта до 4.
И если скажем записать два символа в wstring, первый из которых равен 1 байт а второй 4, то мы получим 8 байт вместо 5, а это уже совсем другие данные. И обратившись по индексу к однобайтовому символу который идёт первым, wstring[0] то мы получим совсем другие данные т.к считаем четыре байта и это уже не будет нашим однобайтовым символом

Возвращаясь к хттп, очень часто приходится взаимодействовать с сервером отправляя/принимая json, парсеры которого как правило рассчитаны именно на utf-8, в таком случае указывать иную кодировку - тоже ссзб
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
05.06.2017, 21:03
Цитата Сообщение от Undisputed Посмотреть сообщение
Символы в ютф-8 имеют различную длину, от 1 байта до 4.
И если скажем записать два символа в wstring, первый из которых равен 1 байт а второй 4, то мы получим 8 байт вместо 5, а это уже совсем другие данные.
В wstring люди держат utf-16. Так что если вы пихаете utf-8 в wstring строку, у вас именно что каша из кодировок.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.06.2017, 21:09  [ТС]
Renji,
Ну под виндой может и да, но в линуксе wchar_t 4 байта

В целом - разобрался
Большое спасибо каждому кто принял участие в обсуждении!
Но если кто то решит добавить инфы, то я буду только рад!)
0
06.06.2017, 06:19

Не по теме:

Цитата Сообщение от nd2 Посмотреть сообщение
0 - 255.
не [-127; 127] ?

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.06.2017, 06:19
Помогаю со студенческими работами здесь

Как правильно перевести std::wstring в std::string ?
Собственно как? :)

Как привести std::wstring к std::string?
Как привести std::wstring к std::string?

Std::string and std::wstring convert
случайно наткнулся на такую вот конвертацию std::string в std::wstring std::string text(&quot;text&quot;); ...

Преобразование из std::string - в std::wstring
Как попроще преобразовать string в широкую строку wstring? Так не получается: #include &lt;iostream&gt; #include &lt;string&gt; ...

Конвертация из std::string в std::wstring
В std::string находятся прочитанные данные из файла, в котором содержатся смешанные данные (что-то на подобии БД, куча таблиц, подтаблиц,с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru