Каково поведение при повторении флага спецификатора printf?

fprintf() семейство функций имеет 5 флаг символы '-', '+', ' ', '#', '0'.

каково указанное поведение, если таковое имеется, когда флаг повторное?

#include <stdio.h>
int main(void) {
  printf("%  dn", 12);     //  12
  printf("%00dn", 34);     // 34
  printf("%++dn", 56);     // +56
  printf("%00*dn", 5, 78); // 00078
  return 0;
}

С моим gcc "i686-pc-cygwin / 4.9.2" я получаю "предупреждение: повторенный флаг '' в формате [-Wformat=]", поэтому я предполагаю, что это правильное поведение--> предупредить пользователя и разрешить повторный флаг.

мне еще предстоит найти C99/C11 руководство по спецификации для этой угловой проблемы найдено при попытке написать синтаксический анализатор формата.

если повторение разрешено, следующий код в порядке. Если повторение не допускается, 2nd 0 - это ширина. Тогда спецификатор имеет 2 ширины 0 и *, который является еще одной проблемой.

// -------v
printf("%00*dn", 5, 78); // 00078

3 ответов


на мой взгляд, стандарт неясен по этому вопросу.

авторы gcc явно придерживались мнения, что повторяющиеся флаги недействительны, поскольку gcc выдает предупреждение по умолчанию для чего-то вроде:

printf("%++d\n", 42);

но это не обязательно говорит нам, что имели в виду авторы стандарта.

стандартные разрешения:

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

флаги -, +, пробел, # и 0. Фраза " ноль или больше флагов*, я думаю, специально предназначена для разрешения разные флаги для объединения. Например, это:

#include <stdio.h>
int main(void) {
    printf("|%6x|\n", 0x123);
    printf("|%-6x|\n", 0x123);
    printf("|%#6x|\n", 0x123);
    printf("|%-#6x|\n", 0x123);
    printf("|%#-6x|\n", 0x123);
}

является допустимым и производит этот вывод:

|   123|
|123   |
| 0x123|
|0x123 |
|0x123 |

в других контекстах стандарт явно указывает, может ли конструкция повторяться или не повторяться. Например, long long int отличается от long int и long int int ошибка синтаксиса. С другой стороны, стандарт явно говорит (N1570 6.7.3p5), что:

если один и тот же классификатор появляется более одного раза в одном и том же спецификатор-квалификатор-список, или сразу или через одно или больше typedefs, поведение такое же, как если бы он появился только один раз.

отсутствие любого такого заявления здесь заставляет меня подозревать, что авторы стандарта не рассмотрим случай повторения одного и того же флага.

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

в любом случае, вы можете выпустить предупреждение, если хотите. Даже если стандарт определяет поведение повторяющегося флага, это все еще, возможно, плохой стиль и стоит предупредить.


в стандарте C (7.21.6.1 функция fprintf) написано только то, что

4 каждая спецификация преобразования вводится символ %. После % последовательно отображаются следующие значения:

- ноль или более флагов (в любом порядке), которые изменяют смысл спецификация преобразования.

поэтому я полагаю, что флаги могут быть повторены. Иначе были бы какие-то ограничения.


стандарт говорит:

7.19.6.1 / 4 ноль или более флагов (в любом порядке), которые изменяют значение спецификации преобразования.

" ноль или более флагов", очевидно, предназначен для того, чтобы указать более одного флага. Имеет смысл, что если флаг повторяется, он имеет то же значение, что и флаг, появляющийся только один раз.