2017-01-17 6 views

ответ

5

Тип может быть повышен согласно нормальным правилам продвижения (плюс два исключения), если это возможно. Если продвижение не представляется возможным, его поведение не определено в C11 на 7.16.1.1 (курсив):

va_arg макрос раскрывается в выражение, имеющее указанный тип и значение следующего аргумента в вызове. Параметр ap должен был инициализирован макросом va_start или va_copy (без промежуточного вызова макроса va_end для того же ap). Каждый вызов макроса va_arg изменяет ap так, что в свою очередь возвращаются значения последовательных аргументов. Тип параметра должен быть указанным типом, чтобы тип указателя на объект , который имеет указанный тип, может быть получен просто путем постфиксации a * для ввода типа. Если нет фактического следующего аргумента, или если тип не совместит с типом фактического следующего аргумента (как это способствовало в соответствии с аргументами по умолчанию поощрений в), поведение не определенно, за исключением следующих случаев за исключением:

  • один тип представляет собой целое число со знаком типа, другой тип представляет собой соответствующий тип целое число без знака, а значение представляется в обоих типов;

  • один тип - указатель на void, а другой - указатель на тип символа.

+0

C89 не является стандартным C и устарел с 18 лет. Стандарт - C11, больше ничего. – Olaf

+0

Я обновил свой ответ, чтобы отразить C11. –

+0

Если вы ссылаетесь на черновик (вы не можете ссылаться на окончательный стандартный документ), используйте итоговый черновик (n1570), промежуточный документ. Пожалуйста, будьте осторожны с самого начала в следующий раз. – Olaf

1

Это неопределенное поведение. @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); 
+0

Спасибо большое @chux – user926918

 Смежные вопросы

  • Нет связанных вопросов^_^