Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printf the value of %n in the same call - senseless?

Tags:

c++

c

I can't find out the intention of the following part of printf specification at cppreference.com:

There is a sequence point after the action of each conversion specifier; this permits storing multiple %n results in the same variable and printing the value stored by %n earlier within the same call.

This reads as if the result of one (or even several) %n conversion specifier(s) could be printed out in the same printf-statement. But I can't find out how this could ever be achieved, because all arguments passed to a call of printf are evaluated before printf's body is entered (there is a sequence point after argument evaluation). Hence, the value of a variable to which a %n would write is evaluated before printf has the chance to overwrite this variable's value with the "number of characters written so far":

#include <stdio.h>

int main( int argc, char* argv[] )
{
    int n = 0;
    printf("Hello, world!%n (%d first n); %n (%d second n)", &n ,n, &n, n);
    // will print out "Hello, world! (0 first n);  (0 second n)"

    return 0;
}

My question: If there isn't any chance of "printing the value stored by %n earlier within the same call", isn't then the respective part of the printf specification senseless or misleading?

What is the actual sense of the c99 standard statement:

7.19.6 Formatted input/output functions (1) The formatted input/output functions shall behave as if there is a sequence point after the actions associated with each specifier.

Is it to reduce the "chances" of getting undefined behaviour?

The question is tagged with c++ and c, because I think that this topic applies the same way to both languages.

like image 988
Stephan Lechner Avatar asked Feb 25 '17 00:02

Stephan Lechner


People also ask

What does %n do in printf?

In C printf(), %n is a special format specifier which instead of printing something causes printf() to load the variable pointed by the corresponding argument with a value equal to the number of characters that have been printed by printf() before the occurrence of %n.

Is %d for double?

%d stands for decimal and it expects an argument of type int (or some smaller signed integer type that then gets promoted). Floating-point types float and double both get passed the same way (promoted to double ) and both of them use %f .

What is %s %d in C?

%s is for string %d is for decimal (or int) %c is for character.

What is %f in printf in C?

What does the "f" in printf stand for? The "f" in printf is short for "formatted" and indicates that the text printed to the screen will be formatted. 2. In the Linux command line, printf is a command that inserts arguments into a user-defined string of text, creating formatted output.


2 Answers

This might be crazy, but I think the following is legal:

char s[2];
s[1] = '\0';
printf("Hi, world!%hhn%s", s, s);

%hhn takes a pointer to char. It writes 10 (the number of characters written so far) to s[0]. It then prints the string s, which is equivalent to "\n" or (char[]){ 10, 0 } (assuming ASCII).

like image 121
melpomene Avatar answered Sep 20 '22 14:09

melpomene


Your code does indeed only print zeros for the reasons you have identified correctly.

The statement in the Standard is still necessary because of blanket wording elsewhere that the behaviour of the program is undefined if an object is written to more than once without intervening sequence point. In effect, the statement is necessary to say that your code does not have undefined behaviour (unlike, say, i = i++;).

like image 32
Kerrek SB Avatar answered Sep 19 '22 14:09

Kerrek SB