ASCII-коды - это числа от 0 до 127.
Стандарт C требует, чтобы представление этих чисел было одинаковым для типов знаков со знаком и без знака.
Значения хранятся в беззнаковыхбитовые поля и объекты типа unsigned char
должны быть представлены в чистом двоичном формате
и
signed char
не должны иметь никаких битов заполнения. Должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и тот же бит в представлении объекта соответствующего беззнакового типа
. Эти положения позволяют безопасно преобразовывать типы со знаком и без знака char
,и (что более важно) между их массивами. Эти преобразования ведут себя предсказуемо и переносимо. Если доступ к объекту типа signed char
осуществляется через значение unsigned char
l, и значение исходного объекта неотрицательно (все коды ASCII), гарантированное значение будет таким же, что и исходное значение. И наоборот, если доступ к unsigned char
осуществляется через значение signed char
l, а исходное значение соответствует диапазону со знаком (все коды ASCII делают), оно гарантированно не изменится. Это важно, потому что различные API часто используют массивы символов неудобной подписи;мы хотим быть уверены, что можем использовать такие API с простым приведением к нашему предпочтительному типу символа.
А как насчет отрицательных значений? Это не ASCII, но мы часто работаем с другими наборами символов и кодировками (например, UTF-8), и они могут иметь отрицательные члены.
Отрицательные значения могут быть представлены точно одним из трех методов.
Если бит знака равен единице, значение должно быть изменено одним из следующих способов:
соответствующее значение со знаком бит 0 обнуляется (знак и величина);
знакбит имеет значение - (2M) (дополнение к двум);
знаковый бит имеет значение - (2M-1) (дополнение к одному).
Здесь мы имеем проблему с отрицательным нулем в представлении знака и величины. Он не может выжить в оба конца через неподписанный тип. Отсюда следует, что некоторые реализации, такие как UTF-8, не могут быть легко поддержаны такой реализацией. Это не проблема для ASCII.
Что касается других целочисленных типов, представление здесь не очень важно. Когда вы используете, например, int
для представления значения ASCII, вы обычно интересуетесь значением, а не представлением. Вы можете безопасно преобразовать значения от 0 до 127 между всеми целочисленными типами, поддерживаемыми C. (Другие целочисленные типы могут иметь биты заполнения, но в остальном большинство вышеприведенного также верно и для них; это не имеет значения, поскольку нормальное программирование почти никогда не затрагивается).
Экзотическая платформа, которая использует другое представление символов, не может поддерживать стандарт C, поэтому писать переносимо для таких платформ не имеет смысла.
Наконец, то же самое верно, если вы заменяете ASCII каким-либо базовымнабор символов фактически используется платформой, за исключением того, что диапазон может быть другим.