C语言 %n 格式说明符在 C 中有什么用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3401156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:05:10  来源:igfitidea点击:

What is the use of the %n format specifier in C?

cprintf

提问by josh

What is the use of the %nformat specifier in C? Could anyone explain with an example?

%nC中的格式说明符有什么用?谁能用例子解释一下?

回答by jamesdlin

Most of these answers explain what %ndoes(which is to print nothing and to write the number of characters printed thus far to an intvariable), but so far no one has really given an example of what useit has. Here is one:

这些答案中的大多数解释了什么(即%n打印任何内容并将迄今为止打印的字符数写入int变量),但到目前为止,没有人真正给出它有什么用途的示例。这是一个:

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

will print:

将打印:

hello: Foo
       Bar

with Foo and Bar aligned. (It's trivial to do that without using %nfor this particular example, and in general one always could break up that first printfcall:

Foo 和 Bar 对齐。(在不使用%n此特定示例的情况下执行此操作是微不足道的,并且通常总是可以中断第一个printf调用:

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

Whether the slightly added convenience is worth using something esoteric like %n(and possibly introducing errors) is open to debate.)

稍微增加的便利是否值得使用一些深奥的东西%n(并且可能会引入错误),这是有争议的。)

回答by Starkey

Nothing printed. The argument must be a pointer to a signed int, where the number of characters written so far is stored.

什么都没打印。参数必须是一个指向有符号整数的指针,其中存储了到目前为止写入的字符数。

#include <stdio.h>

int main()
{
  int val;

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

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

  return 0;

}

The previous code prints:

前面的代码打印:

blah  blah
val = 5

回答by Xzhsh

I haven't really seen many practical real world uses of the %nspecifier, but I remember that it was used in oldschool printf vulnerabilities with a format string attackquite a while back.

我还没有真正看到过该%n说明符在现实世界中的许多实际用途,但我记得它在很早以前就被用于具有格式字符串攻击的老式 printf 漏洞中。

Something that went like this

事情是这样的

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

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

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

where a malicious user could take advantage of the username parameter getting passed into printf as the format string and use a combination of %d, %cor w/e to go through the call stack and then modify the variable authorized to a true value.

恶意用户可以利用作为格式字符串传递给 printf 的用户名参数,并使用%d,%c或 w/e的组合来遍历调用堆栈,然后将授权的变量修改为真值。

Yeah it's an esoteric use, but always useful to know when writing a daemon to avoid security holes? :D

是的,这是一个深奥的用途,但在编写守护程序以避免安全漏洞时知道总是有用的吗?:D

回答by KLee1

From herewe see that it stores the number of characters printed so far.

这里我们看到它存储了到目前为止打印的字符数。

nThe argument shall be a pointer to an integer into which is written the number of bytes written to the output so far by this call to one of the fprintf()functions. No argument is converted.

n参数应是一个指向整数的指针,该整数写入到目前为止通过调用其中一个fprintf()函数写入输出的字节数。不转换任何参数。

An example usage would be:

一个示例用法是:

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

n_charswould then have a value of 12.

n_chars那么将有一个值12

回答by R.. GitHub STOP HELPING ICE

So far all the answers are about that %ndoes, but not why anyone would want it in the first place. I find it's somewhat useful with sprintf/snprintf, when you might need to later break up or modify the resulting string, since the value stored is an array index into the resulting string. This application is a lot more useful, however, with sscanf, especially since functions in the scanffamily don't return the number of chars processed but the number of fields.

到目前为止,所有的答案都是关于%n它的,但不是为什么有人首先想要它。我发现它对sprintf/有点有用snprintf,当您以后可能需要分解或修改结果字符串时,因为存储的值是结果字符串的数组索引。然而,这个应用程序更有用,sscanf尤其是因为系列中的函数scanf不返回处理的字符数,而是返回字段数。

Another really hackish use is getting a pseudo-log10 for free at the same time while printing a number as part of another operation.

另一个真正的黑客用途是在打印一个数字作为另一个操作的一部分的同时免费获得一个伪 log10。

回答by Evan

The argument associated with the %n will be treated as a int* and filled with the number of total characters printed at that point in the printf.

与 %n 关联的参数将被视为 int* 并填充在 printf 中该点打印的总字符数。

回答by jamesdlin

The other day I found myself in a situation where %nwould nicely solve my problem. Unlike my earlier answer, in this case, I cannot devise a good alternative.

有一天,我发现自己处于一种%n可以很好地解决我的问题的情况。与我之前的回答不同,在这种情况下,我无法设计一个好的替代方案。

I have a GUI control that displays some specified text. This control can display part of that text in bold (or in italics, or underlined, etc.), and I can specify which part by specifying starting and ending character indices.

我有一个显示一些指定文本的 GUI 控件。该控件可以以粗体(或斜体、下划线等)显示该文本的一部分,我可以通过指定开始和结束字符索引来指定哪一部分。

In my case, I am generating the text to the control with snprintf, and I'd like one of the substitutions to be made bold. Finding the starting and ending indices to this substitution is non-trivial because:

就我而言,我使用 生成文本到控件snprintf,并且我希望将其中一个替换设置为粗体。查找此替换的开始和结束索引并非易事,因为:

  • The string contains multiple substitutions, and one of the substitutions is arbitrary, user-specified text. This means that doing a textual search for the substitution I care about is potentially ambiguous.

  • The format string might be localized, and it might use the $POSIX extension for positional format specifiers. Therefore searching the original format string for the format specifiers themselves is non-trivial.

  • The localization aspect also means that I cannot easily break up the format string into multiple calls to snprintf.

  • 该字符串包含多个替换,其中一个替换是任意的、用户指定的文本。这意味着对我关心的替换进行文本搜索可能会产生歧义。

  • 格式字符串可能已本地化,并且可能使用$POSIX 扩展名作为位置格式说明符。因此,在原始格式字符串中搜索格式说明符本身并非易事。

  • 本地化方面也意味着我不能轻易地将格式字符串分解为对snprintf.

Therefore the most straightforward way to find the indices around a particular substitution would be to do:

因此,找到围绕特定替换的索引的最直接方法是:

char buf[256];
int start;
int end;

snprintf(buf, sizeof buf,
         "blah blah %s %f yada yada %n%s%n yakety yak",
         someUserSpecifiedString,
         someFloat,
         &start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);

回答by Merlyn Morgan-Graham

It doesn't print anything. It is used to figure out how many characters got printed before %nappeared in the format string, and output that to the provided int:

它不打印任何东西。它用于计算%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;
}

(Documentation for _set_printf_count_output)

(文档_set_printf_count_output)

回答by Sudhanshu Mishra

It will store value of number of characters printed so far in that printf()function.

它将存储到目前为止在该printf()函数中打印的字符数的值。

Example:

例子:

int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);

The output of this program will be

这个程序的输出将是

Hello World
Characters printed so far = 12

回答by user411313

%n is C99, works not with VC++.

%n 是 C99,不适用于 VC++。