Question

int x;
printf("hello %n World\n", &x);
printf("%d\n", x);
Was it helpful?

Solution

It's not so useful for printf(), but it can be very useful for sscanf(), especially if you're parsing a string in multiple iterations. fscanf() and scanf() automatically advance their internal pointers by the amount of input read, but sscanf() does not. For example:

char stringToParse[256];
...
char *curPosInString = stringToParse;  // start parsing at the beginning
int bytesRead;
while(needsParsing())
{
    sscanf(curPosInString, "(format string)%n", ..., &bytesRead);  // check the return value here
    curPosInString += bytesRead;  // Advance read pointer
    ...
}

OTHER TIPS

It can be used to perform evil deeds.

Depends what you mean by practical. There are always other ways to accomplish it (print into a string buffer with s[n]printf and calculate the length, for example).

However

int len;
char *thing = "label of unknown length";
char *value = "value value value"
char *value2="second line of value";
printf ("%s other stuff: %n", thing, &len);
printf ("%s\n%*s, value, len, value2);

should produce

label of unknown length other stuff: value value value
                                     second line of value

(although untested, I'm not near a C compiler)

Which is just about practical as a way of aligning things, but I wouldn't want to see it in code. There are better ways of doing it.

It's fairly esoteric. If you need to replace a placeholder in the generated string later you might want to remember an index into the middle of the string, so that you don't have to either save the original printf parameter or parse the string.

It could possibly be used as a quick way to get the lengths of various substrings.

#include <stdio.h>
int main(int argc, char* argv[])
{
    int col10 = (10 - 1);
    int col25 = (25 - 1);

    int pos1 = 0;
    int pos2 = 0;

    printf("    5    10   15   20   25   30\n");

    printf("%s%n%*s%n%*s\n",                     "fried", 
                            &pos1, col10 - pos1, "green",   
                            &pos2, col25 - pos2, "tomatos");


    printf("    ^    ^    ^    ^    ^    ^\n");

    printf("%d %d\n", pos1, pos2);
    printf("%d %d\n", col10 - pos1, col25 - pos2);

    return 0;
}

I am missing something here for sure. Tomatos is too far to the right.

Here's something from the VS2005 CRT code:

/* if %n is disabled, we skip an arg and print 'n' */
if ( !_get_printf_count_output() )
{
   _VALIDATE_RETURN(("'n' format specifier disabled", 0), EINVAL, -1);
   break;
}

which brings up this:

alt text http://www.shiny.co.il/shooshx/printfn.png

for the following line:

    printf ("%s other stuff: %n", thing, &len);

I'm guessing this is mainly to avoid what @eJames is talking about

you can call

int _get_printf_count_output();

to see if %n support is enable, or use

int _set_printf_count_output( int enable );

to Enable or disable support of the %n format.

from MSDN VS2008

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top