Оба в порядке. Стандарт ISO C11 утверждает в 7.21.6.1 The fprintf function /9
(все различные вызовы *printf
и *scanf
определены в терминах fprintf
и fscanf
), что:
Если какой-либо аргумент не является правильным типом для соответствующей спецификации преобразования, поведение не определено.
Но в разделе для %c
(/8
) также говорится (мой акцент):
Если модификатор длины l
отсутствует, аргумент int
преобразуется в unsigned char
, и результирующий символ записывается.
Фактически, передача int
или char
не имеет значения, поскольку продвижение аргументов по умолчанию выполняется для функций типа varargs за пределами эллипсов (согласно 6.5.2.2 Function calls /6
и /7
и 6.3 Conversions
)
... целочисленные преобразования выполняются для каждого аргумента, а аргументы с типом float повышаются до двойного. Это называется продвижением аргументов по умолчанию.
Многоточие в объявлении прототипа функции останавливает преобразование типа аргумента после последнего объявленного параметра. Аргумент по умолчанию
продвижение по службе выполняется по последним аргументам.
Если int
может представлять все значения исходного типа (как ограничено шириной для битового поля), значение преобразуется в целое; в противном случае он конвертируется в беззнаковое целое. Они называются целочисленными акциями.
Итак, поскольку fprintf
определяется так:
int fprintf(FILE * restrict stream, const char * restrict format, ...);
это означает, что аргумент char
будет в любом случае повышен до int
.
fscanf
- это другое дело. В 7.21.6.2 The fscanf function /12
(снова мой акцент) говорится:
Если модификатор длины l
отсутствует, соответствующий аргумент должен быть
указатель на начальный элемент массива символа , достаточно большой, чтобы принять последовательность. Нулевой символ не добавляется.
Это означает, что вы должны указывать адрес символа (или символьного массива). Если вы предоставите int
, а он не того же размера, вы, вероятно, увидите только часть из этого int
измененного, а остальное останется как какое-то произвольное значение. Например, для восьмибитного байта, четырехбайтовой int
системы с прямым порядком байтов:
+------+------+------+------+
| 0x12 | 0x34 | 0x56 | 0x78 | <- Initial value of int 0x12345678
+------+------+------+------+
| 0x36 | .... | .... | .... | <- Read character '6' (0x36 in ASCII)
+------+------+------+------+
| 0x36 | 0x34 | 0x56 | 0x78 | <- Final value of int 0x36345678
+------+------+------+------+
Вы можете видеть, что другие байты int
остаются нетронутыми (представлены ....
), в результате чего окончательное значение int
является чем-то other чем 0x36
.