Wchar t c что это
Перейти к содержимому

Wchar t c что это

char, wchar_t, char8_t, char16_t, char32_t

Типы char , wchar_t , и char8_t char16_t char32_t являются встроенными типами, которые представляют буквенно-цифровые символы, не буквенно-цифровые глифы и непечатаемые символы.

Синтаксис

Remarks

Тип char был исходным типом символов в C и C++. Этот char тип можно использовать для хранения символов из набора символов ASCII или любого из наборов символов ISO-8859, а также отдельных байтов многобайтовых символов, таких как Shift-JIS или кодировка UTF-8 набора символов Юникода. В компиляторе char Майкрософт используется 8-разрядный тип. Это отдельный тип из обоих signed char и unsigned char . По умолчанию переменные типа char получают повышение до int типа signed char , как если бы /J не использовался параметр компилятора. В разделе /J они обрабатываются как тип unsigned char и получают повышение до int без расширения знака.

Этот тип unsigned char часто используется для представления байта, который не является встроенным типом в C++.

Тип wchar_t — это тип символов, определенный реализацией. В компиляторе Майкрософт он представляет 16-разрядный расширенный символ, используемый для хранения Юникода в кодировке UTF-16LE, собственного типа символов в операционных системах Windows. Функции библиотеки универсальной среды выполнения C (UCRT) используют широкие wchar_t версии символов, а также его типы указателей и массивов в качестве параметров и возвращаемых значений, как и версии расширенных символов собственного API Windows.

char8_t Типы , char16_t и char32_t типы представляют 8-разрядные, 16-разрядные и 32-разрядные символы в ширину соответственно. ( char8_t является новым в C++20 и требуется /std:c++20 параметр компилятора /std:c++latest .) Юникод, закодированный как UTF-8, может храниться в типе char8_t . char8_t Строки и char тип называются узкими строками, даже если используется для кодирования символов Юникода или многобайтовых символов. Юникод, закодированный как UTF-16, может храниться в типе char16_t , и Юникод, закодированный как UTF-32, может храниться в типе char32_t . Строки этих типов и wchar_t называются широкими строками, хотя термин часто относится к строкам wchar_t типа.

В стандартной библиотеке basic_string C++ тип предназначен для узких и широких строк. Используйте std::string , если символы имеют char тип, std::u8string если символы имеют char8_t тип, когда символы имеют char16_t тип, std::u32string std::u16string когда символы имеют char32_t тип, а также если символы имеют тип, а std::wstring также если символы имеют тип wchar_t . Другие типы, представляющие текст, включая std::stringstream и std::cout имеющие специализации для узких и широких строк.

Wchar t c что это

Слышал, что в C++ есть unicode-тип wchar_t.

Как же его применять?

От: Павел Кузнецов
Дата: 29.03.03 08:39
Оценка: 15 (2)

Здравствуйте, Olegator, Вы писали:

O> Слышал, что в C++ есть unicode-тип wchar_t.

По стандарту он не обязательно Unicode, но на большинстве реализаций это именно так.

O>
O> не действует

От: Olegator
Дата: 30.03.03 10:59
Оценка:

Здравствуйте, Павел Кузнецов, Вы писали:

ПК>По стандарту он не обязательно Unicode, но на большинстве реализаций это именно так.

ПК>Вот так:

ПК>

А что есть L в приведённом Вами примере? Это модификатор? Что можно почитать об этом?

Буду признателен за ответ.

От: Михаил Можаев www.mozhay.chat.ru
Дата: 30.03.03 21:24
Оценка:

Здравствуйте, Olegator, Вы писали:

O>А что есть L в приведённом Вами примере? Это модификатор? Что можно почитать об этом?

Буква L в данном случае — часть записи «широкого» (из символов wchar_t) строкового литерала. Такая же, как и кавычки.

C++ Standard, 2.13.2/2 «Character literals»
A character literal that begins with the letter L, such as L’x’, 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. The value of a wide-character literal containing multiple c-chars is implementation-defined.

C++ Standard, 2.13.4/1 «String literals»
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” and has static storage duration, where n is the size of the string as defined below, and is initialized with the given characters.

От: Михаил Можаев www.mozhay.chat.ru
Дата: 30.03.03 21:45
Оценка:

Здравствуйте, Михаил Можаев, Вы писали:

B. Stroustrup, The C++ Programming Language 3ed

4.3.1 Character literals
Wide character literals are of the form L?ab?, where the number of characters between the quotes and their meanings is implementation-defined to match the wchar_t type. A wide character literal has type wchar_t.

5.2.2 String literals
A string with the prefix L, such as L»angst», is a string of wide characters (§4.3, §C.3.3). It’s type is const wchar_t[].

От: DmitryElj
Дата: 31.03.03 09:09
Оценка:

Здравствуйте, Olegator, Вы писали:

O>Слышал, что в C++ есть unicode-тип wchar_t.

O>Как же его применять?

O>Код
O>
O>не действует

Вообще, лучше так:

А потом уже варьировать макрос UNICODE при сборке проекта.

От: Olegator
Дата: 31.03.03 15:42
Оценка:

А как выводить строки типа wchar_t (или TCHAR) в консоль?

Если использовать printf(), то компилятор пишет, что не может привести массив символов char к указанному типу.

От: Micker
Дата: 31.03.03 16:53
Оценка:

Здравствуйте, Olegator, Вы писали:

O>А как выводить строки типа wchar_t (или TCHAR) в консоль?

O>Если использовать printf(), то компилятор пишет, что не может привести массив символов char к указанному типу.

printf() это наследие С.
Используй cout.

От: gloomy rocker
Дата: 01.04.03 05:58
Оценка:

Здравствуйте, Olegator, Вы писали:

O>А как выводить строки типа wchar_t (или TCHAR) в консоль?

O>Если использовать printf(), то компилятор пишет, что не может привести массив символов char к указанному типу.

wchar_t

Возможно я скажу ерунду, а не надо ли для этого сгенерить русскую локаль для всей системы в принципе?

Не хотелось бы таких пререквизитов
Вот так работает:

Во, вот так работает, и арифметика работает. А можно как-то разъяснить смысл сего шаманства и степень его необходимости?

В общем слусае (без костылей) с utf-8 адрессная арифметика не работает.

DISCLAIMER: я не специалист в этой области, я просто умею хорошо находить информацию ☺

В общем слусае (без костылей) с utf-8 адрессная арифметика не работает.

Это понятно, но разве wchar_t сам по себе не костыль для этого?

Хм, странно, но наверное это действительно причина

Дык, имненно так, но в твоём примере просто char . А вот с ним оно как раз не работает.

Ну да, потому я wchar_t и стал тестировать. А оно вон как.

Всё правильно делаешь. Только сначала надо инициализировать (setlocale).

Ок спасибо за помощь

Не за что, с удовольствием. Отмечай как решённую. ☺

ИМХО, чтобы правильно выводило, локаль должна быть UTF-16

либо крестик, либо трусы. Либо ставь локаль с широкими символами, либо используй простую printf, и простые char’ы.

В общем слусае (без костылей) с utf-8 адрессная арифметика не работает.

а как она должна работать, если все символы разного размера? Иные по 1 байту, иные по 2, а всякие ☣ по 3. Ясное дело, что прибавляя 1 char ты переходишь на середину символа, и получается ерунда.

Интересные факты: в UTF-8 арифметика вполне себе работает, но только на одну букву вперед/назад. wchar_t непереносим даже между компиляторами одной платформы. Обращение к пятой/десятой букве теряет смысл после википедия/уникод.

либо крестик, либо трусы. Либо ставь локаль с широкими символами, либо используй простую printf, и простые char’ы.

Не пиши бред. glibc сама умеет конвертировать wchar_t в нужную локаль.

glibc сама умеет конвертировать wchar_t в нужную локаль.

что по твоему значит «сама»? iconv(3) что-ли?

дык _все_ функции *printf(3) конвертируют в юникод, если в ASCII не получается.

Wide characters from the array are converted to multibyte characters

Но это касается *printf(3), и как-то слабо относится к самим wchar_t. Это только запись в файл такая.

Что-то я не пойму о чём ты тут флудишь, всё уже вроде выяснили, всё нормально работает (wchar_t + setlocale = строка юникода с работающей адресной арифметикой)

Интересные факты: в UTF-8 арифметика вполне себе работает, но только на одну букву вперед/назад.

Всё нормально работает и не на одну букву:

Всё нормально работает и не на одну букву:

а это и не UTF-8.

о чём ты тут флудишь, всё уже вроде выяснили, всё нормально работает

видать не все ещё выяснили.

да. Двойку ты прибавлял к wchar_t, а вовсе не к UTF-8.

код удивительным образом совпадает с utf-8 буквой ‘Д’

что в этом удивительного, если у нас wchar_t реализован как UTF-32? Вот только буква Д в utf-8 занимает 2 байта, а у тебя — 4. А вот ☣ занимает 3 байта.

Но это касается *printf(3), и как-то слабо относится к самим wchar_t. Это только запись в файл такая.

Кроме чтения/записи файлов можно ещё конвертировать wide char <-> multibite просто в памяти. Этого недостаточно?

да. Двойку ты прибавлял к wchar_t, а вовсе не к UTF-8.

что в этом удивительного, если у нас wchar_t реализован как UTF-32? Вот только буква Д в utf-8 занимает 2 байта, а у тебя — 4. А вот ☣ занимает 3 байта.

продолжаю непонимать суть твоей проблемы. Радуйся, ☣ влезет в 4 байта и будет правильно работать ☣☣☣☣☣☣☣☣+2

можно ещё конвертировать wide char <-> multibite просто в памяти.

Радуйся, ☣ влезет в 4 байта и будет правильно работать ☣☣☣☣☣☣☣☣+2

будет конечно. Вот только к utf-8 это никак не относится. Ибо ☣ занимает 3 байта, а прибавляется 8 байт (2 символа).

Интересные факты: в UTF-8 арифметика вполне себе работает, но только на одну букву вперед/назад.

Всё нормально работает и не на одну букву:

продолжаю непонимать суть твоей проблемы.

у меня нет проблем. В UTF-8 арифметика вообще не работает, кроме случая ASCII. А у вас она, судя по цитатам, как-то работает.

В частности у тебя она работает в UTF-32. А у анонимуса я не понял как(он код не предоставил).

А у вас она, судя по цитатам, как-то работает.

Какие цитаты вам не понятны?

Интересные факты: в UTF-8 арифметика вполне себе работает, но только на одну букву вперед/назад.

Всё нормально работает и не на одну букву:

Тогда смысл вообще во всех этих wchar_t если все равно арифметика не гарантирована? Кажется она только для utf32 может быть как-то гарантироваться, в остальных случаях это же просто везение. Тогда уж лучше юзать char * а для операций с символами уже тащить что-нибудь в стиле icu.

Ты ведь сам понял, что по сути wchar_t == UTF-32, setlocale с помощью glibc сконвертировал мою utf-8 в utf-32 (или что-то похожее) и теперь строка представляет собой полноценный массив 4-байтных чаров, на котором арифметика не может не работать

Ты ведь сам понял, что по сути wchar_t == UTF-32

это НЕ так. Это только в нашей текущей реализации так. А как оно будет — хз. В венде недавно было 16 бит, ЕМНИП. Да и похоже сейчас 16.

setlocale с помощью glibc сконвертировал мою utf-8 в utf-32

это скорее gcc сконвертировал текст из исходника в UTF-32.

и теперь строка представляет собой полноценный массив 4-байтных чаров, на котором арифметика не может не работать

арифметика-то работает, но вот совершенно непонятно, что с этой строкой делать. Как например имя файла задать? Долбаться с wctomb(3)? Да нафига мне оно надо?

а вот если бы у нас использовался С++, то можно было бы переопределить операторы ++, +, += и прибавлять 1,2 или 3 байта в зависимости от количества единичных старших битов операнда 🙂

Да там 16 бит, я в линуксах whar_t никогда не юзал, предпочитая char и честно был уверен, что там также.

man wcrtomb, man mbrtowc — вроде же оно?

wchar_t это не UTF-8 (и не уникод, да). Настоятельно рекомендую прочитать хотя бы статейку на википедии.

как-то так например:

Ну емае, прочитай уже, а? И покажи код, который гарантированно выдерет букву «й» из слова «плохой» в UTF-8/16/32, а мы еще посмеемся.

wchar_t это не UTF-8 (и не уникод, да). Настоятельно рекомендую прочитать хотя бы статейку на википедии.

Давай я расскажу тебе, ок. wchar_t это исторический тип, когда пошла свистопляска с начальной поддержкой уникода. На некоторых платформах (вин32, ява упс) он 16-битный и не покрывает все символы. UTF-N это способ кодирования кодэпоинтов N-битными словами. Все кодэпоинты *на данный момент* влезают в 20 бит или около того, точно забыл. То, что wchar_t большей частью совпадает с UTF-16/32, не должно вводить в заблуждение. Ну и самое главное: в уникодированном слове «плохой» может быть 6 кодэпоинтов, а может быть 7, опа. Дальше лениво, man NFC NFD. Каждый, кто пытается использовать смещения в уникодных строках обречен на нормализацию (дорого) или провал (фейл). Юзайте поточную обработку и UTF-8 как универсальное представление. /thread

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *