Каково использование %n спецификатора формата в C?

Каково использование %n спецификатор формата в C? Кто-либо мог объяснить с примером?

116
задан Cristian Ciupitu 21 June 2014 в 11:38
поделиться

8 ответов

Ничего не напечатано. Аргумент должен быть указателем на знаковое int, где хранится количество записанных символов.

#include <stdio.h>

int main()
{
  int val;

  printf("blah %n blah\n", &val);

  printf("val = %d\n", val);

  return 0;

}

Предыдущий код выводит на печать:

blah  blah
val = 5
145
ответ дан 24 November 2019 в 02:11
поделиться

Большинство из этих ответов объясняют, что % n делает (то есть ничего не печатает и записывает количество напечатанных символов в int переменная), но до сих пор никто реально не привел пример того, что использует , что у него есть. Вот один из них:

int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");

напечатает:

hello: Foo
       Bar

с выровненными Foo и Bar. (Это тривиально сделать без использования % n для данного конкретного примера, и в целом всегда можно разбить этот первый вызов printf :

int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");

Стоит ли немного добавленное удобство использование чего-то эзотерического вроде % n (и, возможно, внесения ошибок) открыто для обсуждения.)

177
ответ дан 24 November 2019 в 02:11
поделиться

Я не видел много практических применений спецификатора %n в реальном мире, но я помню, что он использовался в старых школьных уязвимостях printf с атакой форматной строки некоторое время назад.

Что-то вроде этого

void authorizeUser( char * username, char * password){

    ...code here setting authorized to false...
    printf(username);

    if ( authorized ) {
         giveControl(username);
    }
}

где злоумышленник мог воспользоваться тем, что параметр username передавался в printf как строка формата, и использовать комбинацию %d, %c или w/e, чтобы пройти через стек вызовов и затем изменить переменную authorized в истинное значение.

Да, это эзотерическое использование, но всегда полезно знать при написании демона, чтобы избежать дыр в безопасности? :D

.
18
ответ дан 24 November 2019 в 02:11
поделиться

Аргумент, связанный с% n, будет рассматриваться как int * и заполнен общим количеством символов, напечатанных в этой точке в printf.

9
ответ дан 24 November 2019 в 02:11
поделиться

Из здесь мы видим, что он хранит количество символов, напечатанных на данный момент.

n Аргументом является указатель на целое число, в которое записывается количество байт, выведенных на данный момент этим вызовом одной из функций fprintf(). Никакой аргумент не преобразуется.

Пример использования:

int n_chars = 0;
printf("Hello, World%n", &n_chars);

n_chars будет иметь значение 12.

13
ответ дан 24 November 2019 в 02:11
поделиться

Пока что все ответы касаются того, что % n делает, но не того, почему это вообще может кому-то понадобиться. Я считаю, что это несколько полезно с sprintf / snprintf , когда вам может понадобиться позже разбить или изменить результирующую строку, поскольку сохраненное значение является индексом массива в результирующей строке. Однако это приложение намного полезнее с sscanf , тем более что функции из семейства scanf возвращают не количество обработанных символов, а количество полей.

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

9
ответ дан 24 November 2019 в 02:11
поделиться

% n - это C99, не работает с VC ++.

-6
ответ дан 24 November 2019 в 02:11
поделиться

Он ничего не печатает. Он используется для определения количества символов, выведенных до появления %n в строке формата, и вывода этого количества в указанный int:

#include <stdio.h>

int main(int argc, char* argv[])
{
    int resultOfNSpecifier = 0;
    _set_printf_count_output(1); /* Required in visual studio */
    printf("Some format string%n\n", &resultOfNSpecifier);
    printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
    return 0;
}

(Документация для _set_printf_count_output)

1
ответ дан 24 November 2019 в 02:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: