Оба правила верны. Вы не правильно их читаете.
Первый, второй -
Порядок вычисления обозначения функции, фактических аргументов и подвыражений внутри фактических аргументов не определен, но перед фактическим вызовом есть точка последовательности.
Это означает, что параметры функции могут оцениваться в любом порядке. Между ними нет последовательности.
Из-за этого звонка типа -
printf("%d, %d and %d\n", i++, i++, i--);
не определен и вызывает UB.
Теперь для первого,
После каждого преобразования, связанного со спецификатором формата ввода / вывода. Например, в выражении printf ("foo% n% d", & a, 42) есть точка последовательности после оценки% n и перед печатью 42
Речь идет не об оценке параметров, а о фактической печати. Всякий раз, когда каждый спецификатор формата, такой как %d
, %c
, %n
оценивается (как для scanf
, так и printf
), он может иметь побочные эффекты. Эти эффекты упорядочены в порядке появления спецификатора формата в строке.
Например
scanf("%d %d", &a, &b); // a and b are integers
Сохранение до a
будет выполнено последовательно перед сохранением до b
Аналогично в случае printf
, как указано в примере,
printf("foo %n %d", &a, 42);
Обновление до a
будет выполнено последовательно перед печатью 42
.
Нет никакого отношения к оценке 42
, &a
, printf
или "foo %n %d"
.