Я хотел бы знать, что соответствует ожидаемому поведению на C, если данный тип данных не соответствует ожидаемому спецификатору формата. Например, для:Несоответствие спецификатора формата C с типом данных
printf("%lu\n", 2);
Я хотел бы знать, что соответствует ожидаемому поведению на C, если данный тип данных не соответствует ожидаемому спецификатору формата. Например, для:Несоответствие спецификатора формата C с типом данных
printf("%lu\n", 2);
Тип может быть повышен согласно нормальным правилам продвижения (плюс два исключения), если это возможно. Если продвижение не представляется возможным, его поведение не определено в C11 на 7.16.1.1 (курсив):
va_arg макрос раскрывается в выражение, имеющее указанный тип и значение следующего аргумента в вызове. Параметр ap должен был инициализирован макросом va_start или va_copy (без промежуточного вызова макроса va_end для того же ap). Каждый вызов макроса va_arg изменяет ap так, что в свою очередь возвращаются значения последовательных аргументов. Тип параметра должен быть указанным типом, чтобы тип указателя на объект , который имеет указанный тип, может быть получен просто путем постфиксации a * для ввода типа. Если нет фактического следующего аргумента, или если тип не совместит с типом фактического следующего аргумента (как это способствовало в соответствии с аргументами по умолчанию поощрений в), поведение не определенно, за исключением следующих случаев за исключением:
один тип представляет собой целое число со знаком типа, другой тип представляет собой соответствующий тип целое число без знака, а значение представляется в обоих типов;
один тип - указатель на void, а другой - указатель на тип символа.
C89 не является стандартным C и устарел с 18 лет. Стандарт - C11, больше ничего. – Olaf
Я обновил свой ответ, чтобы отразить C11. –
Если вы ссылаетесь на черновик (вы не можете ссылаться на окончательный стандартный документ), используйте итоговый черновик (n1570), промежуточный документ. Пожалуйста, будьте осторожны с самого начала в следующий раз. – Olaf
Это неопределенное поведение. @Weather Vane
2
является десятичного числа константы со значением 2 и типом int
.
Когда 2
передается ...
части printf(const char * format, ...);
он подвергается аргументов по умолчанию акции, который в данном случае является int
остается в int
. printf()
принимает 2
как int
.
"%ld"
рассчитывает на соответствие long
. Как long
и int
различные типы:
Если какой-либо аргумент не правильный тип для соответствующей спецификации преобразования, поведение не определено. C11dr §7.21.6.1 9
Даже если размер и диапазон long
и int
одинаковы, то результат будет еще UB - хотя есть дебаты по этому вопросу. На многих платформах UB является приемлемым. В любом случае этого кода следует избегать.
Хорошо включенный компилятор будет предупреждать о неправильном совпадении.
Альтернативы:
printf("%d\n", 2);
printf("%lu\n", 2ul);
printf("%lu\n", 2UL);
printf("%lu\n", 1ul * 2);
printf("%lu\n", (undersigned long) 2);
Спасибо большое @chux – user926918
поведение не определено. –