Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does printf() 'mysteriously' know what I intended to print?

Tags:

c

printf

I forgot to add the accompanying variables to a printf() call. How does printf() know what I want to print?

int successful = 0;//Flag
printf("\nEnter a number to search for: ");
scanf("%d", &data);
successful = search(list, data);
successful? printf("\n'%d' was found\n\n", data) : printf("\n'%d' was NOT found\n\n");

The offending code is the final 'else' of the ternary expression on the last line. I've ran it a few dozen times, and it always seems to print the correct argument in the output.

: printf("\n'%d' was NOT found\n\n");

How does this still work every time?

like image 928
TGIWhiskey Avatar asked Sep 17 '13 04:09

TGIWhiskey


People also ask

What printf actually does?

The printf function (the name comes from “print formatted”) prints a string on the screen using a “format string” that includes the instructions to mix several strings and produce the final string to be printed on the screen.

Is printf safe?

printf(str); fprintf(file, str); A good programmer should always remember that these are extremely unsafe constructions. The thing is, that if a formatting specifier somehow gets inside the string, it will lead to unpredictable consequences.


2 Answers

It may appear to work, but DO NOT RELY UPON THIS.

It probably works because your most recent function call,

successful = search(list, data);

left the data value in the appropriate place on the stack.


It might be useful to mention here that there is a similar serendipity that sometimes occurs if you neglect to include a return statement in a function that declares a single local variable.

int wowee () {
    int val;
    val = 12;

    // <-- no return statement!
}

Sometimes, the local variable val will be returned, probably due to the same kind of stack reuse. But this is also undefined behavior, even if it happens to work.


The moral for both of these cases is to enable more compiler warnings. The compiler can diagnose problems like these, even checking that the format string matches the types of the variables passed to prinf-family functions.

like image 81
luser droog Avatar answered Sep 23 '22 17:09

luser droog


Whoops! That's "Undefined Behavior".

printf("\n'%d' was NOT found\n\n"); // undefined behavior

"Undefined Behavior" is a technical term which basically means... anything could happen. Maybe the right thing could happen, maybe the program will crash, or maybe it will do something else completely.

In this case, maybe the value you want was already on the stack in the right place, so when printf() when to grab its argument it got the right value. This is highly dependent on the use of optimization and the particular ABI you are using, in particular, not all ABIs place values on the stack for non-variadic function calls.

successful = search(list, data);
//                        ^^^^ places "data" on stack as second argument

If you compile your program as 64-bit it might not work any more, since the most common x64 ABI uses registers for the first four non-variadic arguments.

It doesn't change the fact that your code is wrong, and you'll need to fix it if you want to get the right answer consistently.

like image 29
Dietrich Epp Avatar answered Sep 22 '22 17:09

Dietrich Epp