Как int = 65; printf ("% c", a); работать на языке c в GCC? - PullRequest
0 голосов
/ 05 марта 2019
int a=65; 
printf("%c", a);

Я пробовал это в GCC в Ubuntu. Я не знаю версию. Но это сработало, и я хочу знать, как? Потому что, по моему мнению, размер char меньше, чем int, и, следовательно, это не должно было быть возможным.

Ответы [ 4 ]

1 голос
/ 05 марта 2019

7.21.6.1 Функция fprintf

...

8 Спецификаторы преобразования и их значения:
...
<strong>c</strong> Если модификатор длины <strong>l</strong> отсутствует, аргумент <strong>int</strong> преобразуется в <strong>unsigned char</strong>, и полученный символ записывается. Если присутствует модификатор длины l, аргумент <strong>wint_t</strong> преобразуется, как если бы спецификация преобразования ls без точности и аргумент, указывающий к начальному элементу двухэлементного массива wchar_t, первый элемент содержащий аргумент wint_t для спецификации преобразования lc и второй нулевой широкий символ.

C 2011 Онлайн-черновик

Итак, (f)printf ожидает, что аргумент, соответствующий спецификатору преобразования %c, будет иметь тип int, и преобразует его в unsigned char перед форматированием и отображением.

Значение 65, безусловно, может уместиться в unsigned char (0-255), поэтому здесь нет проблем с преобразованием. Если вы передадите целочисленное значение за пределы этого диапазона, то я подозреваю, что в игру вступает следующее:

6,3 преобразования

6.3.1.3 Целые числа со знаком и без знака
...
2 В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или вычитание больше, чем максимальное значение, которое может быть представлено в новом типе пока значение не окажется в диапазоне нового типа. 60)
60) Правила описывают арифметику математического значения, а не значения выражения данного типа.

IOW, если вы передадите значение 321, оно должно "обернуться" обратно в 65 ('A' в ASCII).

1 голос
/ 05 марта 2019

Функция printf имеет следующее объявление:

int printf(const char *format, ...);

Первый аргумент должен быть указателем на массив char, но любые дополнительные аргументы могут быть любого типа, поэтому это неошибка компилятора, если спецификатор формата не соответствует параметру (хотя он равен неопределенному поведению).

Однако это все равно работает из-за ожиданий %c.Со страницы руководства:

Если модификатор l отсутствует, аргумент int преобразуется в символ без знака , и полученный символ записывается.Если присутствует модификатор l, аргумент wint_t (широкий символ) преобразуется в многобайтовую последовательность путем вызова функции wcrtomb (3), причем состояние преобразования начинается в начальном состоянии, а полученная многобайтовая строка записывается.

Из приведенного выше отрывка %c фактически ожидает int и преобразует его в unsigned char для печати.Так что, если это так, то почему фактическая char работает?Это из-за целочисленных повышений .Любой целочисленный тип, меньший int, повышается до int в любом месте, где можно использовать int.Поскольку printf является переменным, он не может проверять типы своих аргументов, поэтому char, переданный в printf, будет повышен до int при вызове функции.

0 голосов
/ 05 марта 2019

Это сработало, потому что просто напечатало значение 65, преобразованное в тип символа в таблице ASCII 65, это буква A, поэтому при вводе:

int a = 65;
printf("%c", a); //---> a coverted to char type.

Проверьте таблицу ASCII здесь Таблица ASCII

0 голосов
/ 05 марта 2019

Это из-за продвижения аргумента по умолчанию .Все, что меньше int, передается как часть списка аргументов переменной printf, перед вызовом преобразуется в int.Следовательно, printf("%c", foo) не может определить разницу между char foo и int foo.(Однако, если значение данных, переданных в %c, выходит за пределы диапазона unsigned char, поведение не определено.)

...