Лучшее понимание printf - Что печатается с "%c", когда предоставленное значение отрицательно?

В Kernighan & Ritchie говорится, что "все печатные символы положительны, когда тип данных char, подписанный или неподписанный, зависит от машины".

Может кто-нибудь объяснить мне значение этой строки? Моя система имеет подписанные символы, но даже с отрицательным значением, скажем, -90, printf печатает символ (хотя это не очень знакомый символ).

3 ответа

Решение

Набор символов ASCII определяет кодовые точки из 0x00 в 0x7F, Неважно, представлены ли они байтовыми значениями без знака или со знаком, так как этот диапазон является общим для обоих.

Печатные символы находятся между 0x20 а также 0x7E, которые являются частью ASCII. Термин печатный символ не определяет все возможные символы в мире, который можно печатать. Скорее это определяется внутри царства ASCII.

Байтовые значения из 0x80 в 0xFF не определены в ASCII, и разные системы присваивают различные символы значениям в этом диапазоне, что приводит к множеству различных типов кодовых страниц, которые идентичны по своему диапазону ASCII, но различаются по этому диапазону. Это также диапазон, в котором значения для байтов со знаком и без знака различаются.

Реализация printf ищет значение одного байта, когда он встречает %c введите свой ввод. Это значение байта может быть подписано или не подписано относительно вашей точки зрения как вызывающей стороны printf функция но printf не знает этого. Он просто передает эти 8 бит в выходной поток, к которому он подключен, и этот поток испускает символы внутри 0x00 а также 0xff,

Понятие знака не имеет смысла внутри конвейера вывода, где выбрасываются символы. Таким образом, отправляете ли вы 255 или -1персонаж отображается 0xFF в конкретной кодовой странице выбрасывается.

-90, поскольку подписанный символ повторно интерпретируется как неподписанный символ, в этом случае его значение равно 166. (Оба значения -90 и 166 равны 0xA6 в шестнадцатеричном формате.)

Вот так. Все двоичные числа положительны. Относитесь ли вы к этому негативно или нет - ваша собственная интерпретация. Используя комплимент общих двух.

8-битное число: 10100110 является положительным 166, что больше 128 (Максимальное 8-битное число с положительным знаком).

Используя знаковое арифметическое число 166 -90.

Вы видите персонажа, у которого значение ascii равно 166.

Используя это в качестве примера:

signed char x = -90;
printf("%c", x);

Целочисленные правила продвижения конвертируют x в int прежде чем передать его как аргумент printf. (Обратите внимание, что ни один из других ответов не упоминает эту деталь, а некоторые подразумевают аргумент в пользуprintf все еще является символом со знаком).

В разделе 7.21.6.1.6 стандарта (я использую стандарт C11) говорится о %c символ флага:

Если модификатор длины l отсутствует, аргумент int преобразуется в беззнаковый char и записывается результирующий символ.

Итак, целое число -90преобразуется в беззнаковый символ. Это означает (6.3.1.3.2):

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

Если беззнаковый символ в вашей системе принимает значения от 0 до 255 (что почти наверняка так и есть), то результат будет -90 + 256 = 166. (Примечание: другие ответы относятся к "младшему байту" или "шестнадцатеричному представлению". предполагая представление дополнения до двух. Хотя это в подавляющем большинстве случаев встречается, стандарт C не гарантирует этого).

Затем символ 166 записывается в стандартный вывод и интерпретируется вашим терминалом.

Другие вопросы по тегам