LINUX.ORG.RU
ФорумTalks

Как много стрингов имеется в C++

 , ,


0

3

Вольный перевод https://blogs.msmvps.com/gdicanio/2018/05/28/how-many-strings-does-c-have/ не претендующий на литературную точность.


(... OK, языковый адвокат придрался бы, посоветовав: «Как много строковых типов...», но я хотел более хитростный заголовок)

Если вы программируете на Python и видите нечто, заключённое в одинарные или двойные кавычки, у вас имеется стринг:


s = 'Connie'

Нечто похожее происходит в Java, со стринговыми литералами вроде «Connie», реализованными как экземпляры класса java.lang.String:

String s = "Connie";

Хорошо.

Теперь давайте (барабанная дробь) войдём в царство C++! И тут начинается веселье.

Итак, давайте рассмотрим эту простую строку кода на C++:

auto s1 = "Connie";

Каков тип s1?

std::string ? массив char[7] ? (эй, "Connie" - это шесть символов, плюс завершающий NULL)

... что-то другое?

Вы можете использовать свою любимую IDE и, наведя указатель мышки на имя переменной, получить выведенный тип. Visual Studio C++ IntelliSense намекает на то, что это const char*. Вау!

А что насчёт "Connie"s ?

auto s2 = "Connie"s;

Нет, это не множественное число от "Connie". И это не искаженный саксонский родительный падеж. Теперь s2 относится к типу std::string ! Спасибо тебе, operator""s включённый в C++14.

Мы уже закончили? Разумеется нет! Не забывайте - это C++!

Например у вас может иметься u8"Connie", который представляет юникодный UTF-8 литерал. И разумеется, нам необходимо обсуждение на StackOverflow для того, чтобы выяснить "Как u8-литералы должны работать".

А ещё не забудте о L"Connie", u"Connie" и U"Connie" которые представляют const wchar_t*, const char16_t* (закодировано в UTF-16) и const char32_t* (закодировано в UTF-32) соответственно.

Ну теперь мы закончили, правда? Ещё нет!

На самом деле вы можете сочетать приведённые выше префиксы со стандартным s-суффиксом, например: L"Connie"s - это std::wstring, а U"Connie"s - это std::u32string и так далее.

Закончили, правда? Ещё нет! На самом деле нам надо учесть ещё и сырые (raw) стринговые литералы. Например: R"(C:\Path\To\Connie)" который является const char* (константным символьным указателем) на “C:\Path\To\Connie” (что ж, это позволяет избавиться от кодирования '\' при помощи управляющей последовательности '\\').

Так же не забывайте о сочетании сырых стринговых литералов со всеми префиксами и s-суффиксом, разобранными выше. Например: LR"(C:\Path\To\Connie)", UR"(C:\Path\To\Connie)", LR"(C:\Path\To\Connie)"s, UR"(C:\Path\To\Connie)"s и так далее!

Ой и в добавок к стандартному классу std::string и прочим стандартным, основанным на std::basic_string, определениям строковых типов (таких как std::wstring, std::u16string, std::u32string и т.д.) имеются платформо/библиотечно зависимые классы, такие как CString, CStringA и CStringW в ATL/MFC, QString в Qt и wxString в wxWidgets.

Вау! Не удивлюсь, если я упустил какие-то другие вариации стрингов.

P.S. Со всем этим стринговым разнообразим (наверное слишком большим...), как насчёт добавления в стандартную библиотеку C++ некоторых удобных стринговых операций, как например обрезание пробелов или преобразование символов в заглавные или в строчные? При этом в стандартной библиотеке C++ уже имеются функции «для ракетостроения», такие как функции Бесселя. А ведь ещё в стародавние времена MFC там в CString уже были такие функции как Trim, MakeLower и MakeUpper и это далеко не весь список.

★★★★★

Последнее исправление: bbk123 (всего исправлений: 10)

Ответ на: комментарий от utf8nowhere

Тогда зачем добавили char8_t как новый базовый тип? Чему будет равен sizeof(char8_t) если char больше 8 бит? Напоминаю, sizeof(char) == 1 при любом размере char.

bbk123 ★★★★★
() автор топика
Последнее исправление: bbk123 (всего исправлений: 1)
Ответ на: комментарий от bbk123

Тогда зачем добавили char8_t как новый базовый тип?

Чтобы отличать строки в execution character set от строк только в UTF-8. До этого литералы того и другого имели тип const char[...], теперь их можно отличать на уровне типов.

Ещё чтобы от алиасинга со всем чем можно избавиться.

Чему будет равен sizeof(char8_t) если char больше 8 бит?

sizeof(unsigned char). (https://timsong-cpp.github.io/cppwp/n4861/basic.fundamental#9.sentence-1 https://timsong-cpp.github.io/cppwp/n4861/basic.fundamental#def:underlying_type)

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Причём тут sizeof(unsigned char) ? Этот unsigned char может быть 16 бит и это не char8_t, о sizeof которого я спросил. Если у меня массив из char8_t у которых «underlying type is unsigned char», что будет при записи такого массива в файл? Выравнивание каждого char8_t по unsigned char ?

bbk123 ★★★★★
() автор топика
Ответ на: комментарий от bbk123

Причём тут sizeof(unsigned char) ?

При том, что это underlying type для char8_t и у них должен быть одинаковый object representation. Который определён через sizeof.

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Предположим CHAR_BIT == 16. Массив из двух char8_t записывается в файл. Сколько байт запишется и почему?

bbk123 ★★★★★
() автор топика
Ответ на: комментарий от bbk123

Предположим CHAR_BIT == 16. Массив из двух char8_t записывается в файл. Сколько байт запишется и почему?

Сначала найди систему с CHAR_BIT == 16 и API для работы с файлами принимающим char8_t. В доках будет написано.

Ну а так 2 байта. По определению.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 2)
Ответ на: комментарий от utf8nowhere

Как же 2 байта, когда «underlying type is unsigned char», который для двух char8_t с CHAR_BIT == 16 равен четырём?

bbk123 ★★★★★
() автор топика
Ответ на: комментарий от bbk123

Как же 2 байта, когда «underlying type is unsigned char», который для двух char8_t с CHAR_BIT == 16 равен четырём?

Чиво? Что значит что «underlying type … равен четырём»?

utf8nowhere ★★★
()
Ответ на: комментарий от bbk123
Ответ на: комментарий от utf8nowhere

Ну вот там как раз упоминается alignment requirements. Каков размер массива из двух unsigned char когда CHAR_BIT == 16? Те самы четыри байта вместо двух. А теперь мы записывает массив из двух char8_t и получаем..?

bbk123 ★★★★★
() автор топика
Ответ на: комментарий от bbk123

Каков размер массива из двух unsigned char когда CHAR_BIT == 16? Те самы четыри байта

sizeof(unsigned char[2]) == 2 * sizeof(unsigned char) == 2. The sizeof operator yields the number of bytes occupied by a non-potentially-overlapping object of the type of its operand, так что размер массива из двух unsigned char два байта.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 1)
Ответ на: комментарий от utf8nowhere

Видимо там немного о других байтах говорится, необязательно о 8-и битных. Потому что при любом значении CHAR_BIT, даже при CHAR_BIT == 16, sizeof(unsigned char) == 1. А я спрашивал исключительно о 8-и битных байтах.

https://en.wikipedia.org/wiki/Sizeof

sizeof is a unary operator in the programming languages C and C++. It generates the storage size of an expression or a data type, measured in the number of char-sized units. Consequently, the construct sizeof (char) is guaranteed to be 1.

bbk123 ★★★★★
() автор топика
Ответ на: комментарий от bbk123

Ну про любые преобразования между внутренним и внешним представлением — в документации платформы/преобразующих функций.

utf8nowhere ★★★
()
Ответ на: комментарий от bbk123

Что же там говорится?

ХЗ. Я не знаю систем с CHAR_BIT ≠ 8, которые общаются с миром, ожидающим октеты.

Что char8_t не совсем 8 бит? :-)

Да и char[16|32]_t не обязательно 16/32 бит. В стандарте сказано что у них underlying type это uint_least[16|32]_t (который, впрочем, не может отличаться от uint[16|32]_t, если таковые доступны на данной платформе).

utf8nowhere ★★★
()
Ответ на: комментарий от Harald

И тут сразу возникает куча нюансов, а какого размера должен быть этот «лен»?

Эта структура должна быть шаблоном. Какой размер нужен в проекте, такой и используем.

Psilocybe ★★★★
()
Ответ на: комментарий от bbk123

Это почему же? И почему Бессель не базовая функциональность? Мне вот например никогда никакие wchar и проч. не нужны были, и вообще пофиг, какой там юникод внутри. Как и функция Бесселя мне тоже не нужна. Но C++ я использую. А с std::string vs. char* сталкивается каждый, кто изучает C++.

seiken ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.