Oct 16, 2020 21:35
Что тип String в классическом понимании - это не совсем тип. Нет, ну конечно, тип, но недалеко ушедший от Array[]
И отсутствие понимания этого нам стоило всех тех мучений с кодировками, пока гордиев узел не разрубили, пересадив всех на UTF-8.
Суть в чём. Тип должен определять, во-первых, хранилище бит, в котором будет сохраняться переменная этого типа.
Например, для char это 8 бит, для char[] это последовательность таких 8-битных блоков известной - char[10] или неизвестной длины (как для ASCIIZ строк).
Во-вторых - правила выполнения неких осмысленных в прикладном плане операций.
А во-вторых, самое главное - тот, как имеющуюся последовательность бит сопоставить с теми объектами, над которыми мы, собственно, выполняем операцию.
Для чисел это всё сделали производители процессоров. Целые числа (знаковые) всегда представлены с доолнительном коде, и 0xFF - это на всех современных архитектурах -1, а не -127, как было бы, если бы это число было бы представлено в обратном коде.
Для чисел с плавающей точкой тоже всё урегулировано - принят стандарт IEEE754
А вот с символьными данными такого нет. Да, есть стандарт ASCII, но он покрывает только потребности того, что зашифровано буквой A. Для стран с другими алфавитами понадобилось его расширять и появилось множество кодовых таблиц. И вот тут возникает проблема.
Тип string - это просто последовательность кодов. В каком кодовой странице эти коды - в типе информации нет.
Для чисел проблема разных кодировок тоже есть - например байт 0x80 - это может быть 128, а может быть -128. Но - с числами эта проблема решена - есть int, а есть unsigned int. И, глядя на тип переменной, сразу понятно, что данная последовательность бит означает. А как быть со string?
Решений могло бы быть два (в общем то дополняющих друг друга):
1. Использовать тип TaggedString - когда пару байт мы отводим под charset, это вызывает оверхэд, но зато мы можем получить строку, правильно её вывести пользователю, и записать в вывод в том же виде, как она была, делая перекодировку или нет по необходимости.
2. Сделать так же как с int/uint - ввести типы ASCIIString, KOI8String, CP866String и т.д. - тут конечно возникает куча гемороя с функциями перекодировки, но нет лишний пары байт при хранении.
А тот бардак с кодировками, который возник - лишь из-за того, что информацию о кодировке программист хранил в какой-то отдельной переменной, или просто предполагал - и в самом неподходящем месте эту информацию забывают подтянуть, берут не оттуда, предполагают не то, и т.д.
Ну типа, вот у нас кодировка, и все строки в этом модуле в ней, кроме вот этих трёх переменных, а потом в процессе разработки какие именно переменные-исключения имеются в виду забывается. Вроде как оверхед меньше (одно указание на кодировку для набора переменных), но средств защититься от ошибок программиста по использованию кодировок, кроме явного указания субтипа, насколько я знаю, нет.