Reputation: 4360
I ran into a weird problem with printf()
today. But I couldn't find its answer even after analyzing it. Hence sharing it here. I tried these three printf()
statements:
printf("\nValue of this division is %f", (double)873/(double)65);
It prints correct output as expected.
printf("\nSome message with an integer here %d followed by floats %f, %f, %f", 2013, 987/432, 873/65, 983/81);
Given me wrong values (Because I didn't cast them to double?)
printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");
printf()
crashed here! And this raises me two questions:
I saw the "FormatOutput(LPCSTR formatstring, ...)" example given in MSDN in which they allocate fixed width destination buffer then call vsnprintf()
with it. I believe printf()
works along the same line. But I didn't find anywhere internal buffer size of printf()
. If it dynamically allocates memory, how does it then calculates buffer size?
printf()
crashes on above line because vsnprintf()
also crashes there (Yes I tried FormatOutput
sample code given for vsnprintf()
with above parameters). But why would would it crash ultimately?
Upvotes: 3
Views: 2859
Reputation: 2033
printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");
As explained by earlier answers, the result of an integer division is an integer. So 987/432
would result in a (most likely) 32-bit int
on your system. But %f
tells printf
to expect a 64-bit double
! Thus, it reads the combined memory space of 987/432
and 873/65
- giving garbage result. And following that, another 64-bit double
: 983/81
and pointer to "Some..."
- garbage again.
Another 64-bit double (the third %f
) follows, which is now out of bounds! It's probably luck that your second example didn't crash right there. By the time it reaches %s
, printf()
would look for a pointer... if it doesn't crash from the out of bounds access, it would from trying to access invalid memory address of the resulting pointer.
printf()
doesn't need to allocate memory. It writes directly to the standard output (e.g. your terminal window)
Any variation of the the printf
family would crash just the same.
Upvotes: 2
Reputation: 106122
No need to use (double)873/(double)65
for casting, simply you can use (double)873/65
or even 873.0/65
. And dividing an int
by an int
will always result in int
value. To print double
, you can use 987.0/432
or simply 987f/432
for printing float
. Both will work.
Upvotes: 2
Reputation: 43389
In your example, you are supplying the results of integer division to printf (...)
when it expects double-precision floating-point. Either use single- or double-precision floating-point division or correct your format string. Note that single-precision floating-point is automatically promoted to double-precision, just as char and short are promoted to int when used in conjunction with variable argument lists.
As a thought experiment, you should consider the myriad of things that may happen in a hypothetical scenario where you cast a pointer from a 32-bit data type to 64-bit type and then attempt to dereference it. Just as in the pointer scenario illustrated above, you are dealing with undefined behavior as a result of improperly communicating your data types. There are a number of nasty things that can occur and cause your program to crash if you invoke undefined behavior.
Nevertheless, some compilers are capable of parsing your format string at compile-time and validating it against the list of arguments you supply printf (...)
. You may want to look at the available compiler warnings on your system so you can avoid this in the future.
Upvotes: 2
Reputation: 154045
You promised to print double
s but you are passing in int
s: 987/432
is an int
. If you want this value to be a double
you'd use 987.0/432
, for example.
Upvotes: 6