LINUX.ORG.RU

Какой нативный тип данных для строк в линукс?

 , , ,


0

4

Собственно, интересует такой вопрос. Какой нативный строковый тип данных в линукс (убунта, дебиан, центос)? К примеру, в винде все внутренности в UTF-16LE, Анси функции просто конвертируются в юникод. А как здесь? Можно ли юзать обычный 8 битный char , или лучше что-то другое (чтобы работало везде).

Можно ли юзать обычный 8 битный char

Нет (saahriktu, тебя не спрашивали).

или лучше что-то другое (чтобы работало везде).

Если «везде» — это «на всех дистрибутивах linux», то, как я понимаю, wchar_t должно хватить. А если и на винду надо переносить, то уже будут нюансы. В винде, как всегда, пошли своим путём:

В Windows API тип wchar_t именуется как WCHAR и имеет фиксированный размер 16 бит, что не позволяет кодировать весь набор символов Unicode (больше 1 миллиона). Поэтому нарушается стандарт ANSI/ISO C, который требует, чтобы символьный тип wchar_t поддерживал все представимые в системе символы в одном объекте wchar_t

https://ru.wikipedia.org/wiki/Широкий_символ

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

utf-8 ascii-совместимый, соотвтественно char* без всяких там wchar
wchar_t же лучше не использовать т.к он везде разной ширины

mittorn ★★★★★
()

В Linux нативный тип это набор байт. Не utf-8 и не char*.

Не utf-8, так как имя файла может быть невалидной utf-8 последовательностью

Не char*, так как ограничения есть у типа файловой системы, например у ext4: Любые символы, кроме NUL, /

https://ru.wikipedia.org/wiki/%D0%A1%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%D1%8B%D1%85_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC

Большинство языков забивают и используют char* или utf-8 или utf-16

Но, например, в Python есть нативный тип строк для Linux это: b""

В rust: https://doc.rust-lang.org/std/ffi/struct.OsString.html

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 3)

Какой нативный строковый тип данных в линукс

Никакой. Нативный тип только один - последовательность байт. Как оно будет интерпретироваться системой и программами в тех случаях, когда является представлением строки, зависит от текущей локали и фантазии автора программы.

no-such-file ★★★★★
()
Ответ на: комментарий от mittorn

utf-8 ascii-совместимый, соотвтественно char* без всяких там wchar

Тогда не будут корректно работать операции со строками. Если нужно взять конкретный символ, например.

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

А что есть один символ в какой-нибкдь арабской вязи например? Не надо надеяться что такие действия всегда будут работать корректно. Если тебе просто надо передать, скопировать или склеить строку - utf-8. Рендерить utf-8 тоже можно т.к рендер в должен работать со строкой целиком, при необходимости декодируя её в кодпоинты.
А в эмодзи к примеру первый кодпойнт задаст эмодзю, второй укажет цвет кожи, третий гендер. Так что использовать utf32 и бить строку по кодпоинтам тоже нельзя - у кого-то потеряется гендер или цвет кожи и он подаст на вас в суд. Так что если это не текстовый редактур - utf-8 предпочтительнее.

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 1)

Можно ли юзать обычный 8 битный char

И можно, и нужно. Но лучше не использовать C.

deadplace
()
Ответ на: комментарий от te111011010

какой же ты ламер. Никто в жизни не использует wchar_t где-то кроме винды

zendrz ★★
()

откуда такой вопрос? Т.к ответ на него не будет точным, лаконичным и полным, то лучше поясни. И сразу еще: почему ты решил задуматься и тебе не понравился «char *»?

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

Тогда не будут корректно работать операции со строками. Если нужно взять конкретный символ, например.

Если вопрос был о ядре, во всех системных вызовах именно null-терминированный char *. Исключение составляет драйвера файловых систем, где unicode требуется не просто так, а именно с поддержкой эквивалентности большого и малого регистра букв и более не для чего. То есть опять же в основном для MS-файловых систем.

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

имя файла может быть невалидной utf-8 последовательностью

Интересно. Пример такой последовательности мож скинуть?

anonymous
()

практично как уже указали utf8

для общего решения - найдёшь сообщи тут

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

Пример такой последовательности мож скинуть?

Практически любое имя в koi8-r, cp1251, iso-8859-5 на кириллице.

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

Практически любое имя

Не интересует любое. Дай что-нибудь конкретное, чтобы понять, о чём ты?

anonymous
()
Ответ на: комментарий от NeXTSTEP

echo привет | iconv -t koi8

echo привет | xxd
0000000: d0bf d180 d0b8 d0b2 d0b5 d182 0a

echo привет | iconv -t koi8 | xxd
0000000: d0d2 c9d7 c5d4 0a

Мож я чёто не догоняю, но никакого краша я не вижу. Переврится как нефиг делать. Или за что речь?

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

koi8-r: «а» - \xC1 - \b11000001
iso-8859-5: «a» - \xD0 - \b11010000
Для utf-8 префикс 110xxxxx означает, что далее должен следовать еще один байт этого символа, соответствующий маске 10xxxxxx, то есть варианты «аа», «ааа», ... в этих кодировках тоже невалидные последовательности utf-8.

cp1251: «а» - \xE0 - \b11100000
Для utf-8 префикс 1110xxxx означает, что далее должны следовать еще два байта этого символа, оба 10xxxxxx, то есть варианты «аа», «ааа», ... в cp1251 тоже невалидные последовательности utf-8.

Подробнее: https://ru.wikipedia.org/wiki/UTF-8

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

Да чем она невалидная то? И для кого? Для какого ЯП?

1) несоответствием utf-8 (документам RFC 3629 и ISO/IEC 10646 Annex D), см. https://ru.wikipedia.org/wiki/UTF-8
2) для всех
3) для любого

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

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

Английская версия более полная: https://en.wikipedia.org/wiki/UTF-8

На всякий случай: лежит у вас на диске в качестве имени файла последовательность байт: \xC1\xC1\0. Она является валидным кириллическим именем в koi8-r, но не является валидной последовательностью utf-8. Вопрос ваш был именно о примере такой ситуации

имя файла может быть невалидной utf-8 последовательностью

Интересно. Пример такой последовательности мож скинуть?


Если появились новые вопросы, сформулируйте и задайте.

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

Если появились новые вопросы

Вопрос старый. Что с этим именем будет «не так»? Ядро его будет неправильно обрабатывать? Или «кто»?

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

Вопрос старый.

... но до настоящего времени не звучавший ;-)

Что с этим именем будет «не так»? Ядро его будет неправильно обрабатывать? Или «кто»?

До недавнего времени (до введения поддержки регистронезависимости в нативные ФС) ядру было глубоко фиолетово, что там в нативной ФС в имени, достаточно было знать, что там последовательность байт, завершающаяся нулём и не содержащая внутри '/' и \0, что прочитало, то и отдало, что дали, то и записало. Как эту последовательность проинтерпретирует вызывающий юзерспейс — его личное дело.

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

$ echo $LANG
ru_RU.utf8

$ mkdir test; cd test
$ touch $'\xc1'   # "а" в koi8-r

$ /bin/ls
?

$ /bin/ls -b   # оно же --quoting-style=c
\301

$ /bin/ls --quoting-style=literal | iconv -f koi8-r
а

$ cd ..; rm -r test

В 'man ls' можно почитать про другие варианты квотирования «кривых» имён (см. --quoting-style=).

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

создавать кривые с точки зрения юзерспейса имена не запрещено.

Тогда контекст «невалидности» для меня «страноват»? В другом разделе я б не стал спрашивать, но в этом - какой то винегрет получается. Что имелось то в виду? Что не «отображается» какбэ? Или что?

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

Тогда контекст «невалидности» для меня «страноват»?

Не всякая последовательность байт является валидной последовательностью utf-8.
Валидная последовательность utf-8 соответствует определенным критериям, которые, в свою очередь, являются прямым следствием реализации тех целей, для которых создавалась utf-8:
1) возможность передачи туда, где ожидалась asciiz строка,
2) возможность кодирования более 255 символов (используется префиксное кодирование),
3) возможность самосинхронизации,
и еще кое-что, о чём хорошо и подробно написано в английской версии статьи про utf-8:
https://en.wikipedia.org/wiki/UTF-8
Да, ссылка уже была выше. Да, пересказывать здесь не буду.

Невалидной строка может стать по многим причинам, в том числе, в некоторых случаях работы с ней как с однобайтовой строкой. Очевидно, что использовать результат такой обработки можно не всегда и с определенными оговорками. Поэтому часто невалидная utf-8 последовательность трактуется как испорченная строка (например, iconv без специальных ключей поступит с ней сильно нехорошо).

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

использовать результат такой обработки можно не всегда

Ага. То есть «невалидной» она становится при попытке её «обработать». Так сказать, «сложности в обработке». Теперь контекст понятнее.

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

То есть «невалидной» она становится при попытке её «обработать».

Не обязательно. Например тут:
Какой нативный тип данных для строк в линукс? (комментарий)

показан пример попытки проинтерпретировать в качестве строки в utf-8 те строки, которые были изначально записаны в других кодировках.

Пример не надуманный, достаточно почитать носитель с именами, скажем, в koi8-r в окружении с utf-8 локалью, получится ровно так:
Какой нативный тип данных для строк в линукс? (комментарий)

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

у кого-то потеряется гендер или цвет кожи и он подаст на вас в суд

Рука-лицо. Всё таки тому, кому пришла идея тащить смайлы в Unicode надо прищемить что-нибудь.

ls-h ★★★★★
()

Пользуюсь исключительно char*, проблем нет.

OnlyAsk
()
Ответ на: комментарий от bormant

показан пример попытки проинтерпретировать

А я чо сказал?

«невалидной» она становится при попытке её «обработать»

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

А я чо сказал?

Ну, это, скажем честно, разные ситуации:
1) была валидная utf-8 последовательность, которую испортили обработкой (data loss),
2) есть последовательность, которую ошибочно посчитали utf-8 и она невалидная последовательность utf-8.

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

Ну, это, скажем честно, разные ситуации:

Будьте добры, окажите любезность, описанные Вами «проблемы» в отдельные, «близкие по смыслу» топы. В этом топе каким боком всё это прибабахивается?

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

В этом топе каким боком всё это прибабахивается?

Вот этим:

Можно ли юзать обычный 8 битный char , или лучше что-то другое

Видя в объявлении char*, о той строке можно сказать только, что на конце '\0', да и то не всегда...

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

Невалидная UTF-8 последовательность, это которую невозможно конвертировать в юникодовский кодпоинт. Байт 11111xxx невалиден. Последовательность байт 110xxxxx 0xxxxxxx невалидна. Последовательность байт 1110xxxx 0xxxxxxx невалидна. И там ещё много невалидных последовательностей.

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

Чего-чего?! Либастрал подвезли?!

Говорю, не читатель чукча, чукча писатель...

Видя в объявлении char*, о той строке можно сказать только, что на конце '\0', да и то не всегда...

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

писатель…

Писатель? Так бы сразу и сказал.

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

Если под char* ты имеешь ввиду последовательность любых байт, кроме нулевого, то там нет понятия невалидности. Но char* используется как для последовательности любых байт, так и для последовательности байт в мультибайтовой кодировке. Например, в UTF-8 или в Shift-JIS. В этом случае есть понятие невалидных последовательностей. Ты же просил пример невалидной UTF-8 последовательности. Я привел пример.

iliyap ★★★★★
()

Ядро Linux ничего не знает про кодировку. В частности, этому способствует чувствительность к регистру - ядру не нужно никак интерпретировать символы, а только сравнивать байт с байтом. Соответственно, под такой формат подходят либо однобайтовые кодировки, либо UTF-8. Соответственно, есть смысл продолжать эту линию и обращаться со строками как с массивами байт. Естественно, возникнет желание сделать раз и навсегда, потому вариант один - UTF-8.

Да, в винде UTF-16 (порядок байтов значения не имеет), и на фоне регистронезависимости это очень грамотный ход, поскольку позволяет хранить подавляющее число текста в виде «один символ - одна ячейка», при этом используя минимальный объем памяти.

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

А если и на винду надо переносить, то уже будут нюансы. В винде, как всегда, пошли своим путём:

В Windows API тип wchar_t именуется как WCHAR и имеет фиксированный размер 16 бит, что не позволяет кодировать весь набор символов Unicode (больше 1 миллиона). Поэтому нарушается стандарт ANSI/ISO C, который требует, чтобы символьный тип wchar_t поддерживал все представимые в системе символы в одном объекте wchar_t

Правило очень простое, и оно записано в современных стандартнах C/C++: wchar_t зависит от реализации. «Все представимые в системе символы» фактически и значит «зависит от реализации», потому что откуда вы знаете, какие у меня в системе все представимые символы? Доходило до того, что wchar_t был однобайтовым. Но комитетным седокам почему-то это было не очевидно.

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

Нет такого типа в языке C (судя по тегам, вопрос именно про него)

Есть: char32_t.

byko3y ★★★★
()

Его нет.

В С как языке нет и никогда не было строк. В прочих случаях — зависит от языка и библиотеки. Файлы (включая имена файлов) в современных дистрибутивах обычно в локали юзера, но это никем не гарантированно.

в винде все внутренности в UTF-16LE

glibc предполагает, что все внутренности — в кодировке локали, она обычно utf-8 по дефолту. Гарантий нет, «работало везде» зачастую не будет работать у маргиналов, поставивших какой-нибудь EUC если ты специально не предусмотришь это.

Обычно на всё это забивают и поддерживают utf-8 снаружи (в файлах/сети), а внутри софта — иногда utf-16, utf-32 в зависимости от используемых библиотек.

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

Поэтому нарушается стандарт ANSI/ISO C, который требует, чтобы символьный тип wchar_t поддерживал все представимые в системе символы

Этот стандарт бесполезен потому, что «представимые в системе символы» == grapheme clusters. На уровне языка они поддерживаются в каком-нибудь swift, а в сях — в лучшем случае через уйму костылей и вызовов libicu.

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