Можно ли% c дать отрицательный аргумент int в printf? - PullRequest
0 голосов
/ 07 мая 2020

Могу ли я передать отрицательное int в printf при печати через спецификатор формата %c, поскольку при печати int преобразуется в беззнаковый char? printf("%c", -65); действителен? - Я пробовал это на G CC, но на выходе получил ромбовидный символ (с вопросительным знаком внутри). Почему?

1 Ответ

4 голосов
/ 07 мая 2020

Абсолютно да, если char знаковый тип. C позволяет char быть подписанным или беззнаковым , а в G CC вы можете переключаться между ними с помощью -funsigned-char и -fsigned-char. Когда char подписан, это то же самое, что и

char c = -65;
printf("%c", c);

При переходе в printf переменная char будет иметь расширенный знак до int, поэтому printf также увидит - 65, как если бы оно было передано с константы. printf просто не имеет возможности различать printf("%c", c); и printf("%c", -65); из-за продвижения по умолчанию в переменных c функциях.

Результат печати зависит от кодировки символов . Например, в кодировках ISO-8859-1 или Windows -1252 вы увидите ¿, потому что (unsigned char)-65 == 0xBF. В UTF-8 (который является кодировкой переменной длины) 0xBF не допускается в качестве символа в начальной позиции. Вот почему вы видите � это символ замены для недопустимых байтов

Скажите, пожалуйста, почему кодовая точка от 0 до 255 не отображается в символы от 0 до 255 в символах без знака. Я имею в виду, что они неотрицательны, поэтому не следует ли мне просто просматривать набор символов UTF-8 для их соответствующих значений?

Сопоставление выполняется не по относительной позиции в диапазоне, как вы думали , т.е. кодовая точка 0 отображается на CHAR_MIN, кодовая точка 40 сопоставляется с CHAR_MIN + 40, кодовая точка 255 отображается на CHAR_MAX ... В системах с двумя дополнениями это обычно простое сопоставление, основанное на значении битовой комбинации, когда рассматривается как неподписанный. Это потому, что значения обычно обрезаются из более широкого типа. В C символьный литерал, например 'a', имеет тип int. Предположим, что 'a' отображается в кодовую точку 130 в некотором теоретическом наборе символов, тогда следующие строки эквивалентны

char c = 'a';
char c = 130;

В любом случае c будет присвоено значение 'a' после преобразования в char, т.е. (char)'a', что может быть отрицательным значением.

Таким образом, кодовые точки от 0 до 255 отображаются в символы от 0 до 255 в беззнаковых символах. Это означает, что кодовая точка 0x1F будет сохранена в виде символа (со знаком или без знака) со значением 0x1F. Кодовая точка 0xBF будет сопоставлена ​​с 0xBF, если char беззнаковый, и -65, если char подписан

Я предполагаю 8-битный char для всего вышеперечисленного. Также обратите внимание, что UTF-8 - это кодировка для набора символов Unicode, это не кодировка сама по себе, поэтому вы не можете искать кодовые точки UTF-8

...