Reputation: 2903
scanf needs %lf for doubles and printf is okay with just %f
So, why is printf
and scanf
okay with %d?
This is what I think the reason is:
A floating point (%f
) uses exactly 64 bits whereas a double floating-point number (%lf
) uses at least 32. The compiler doesn't know how many bits to assign to a variable that is being scanned in by scanf
, so we use %lf
to tell the compiler that it needs to be at least 32 bits.
Okay... but then why do we use %d
for both scanf
and printf
? Why not %ld
and %d
? %ld
doesn't exist in C for starters. %d
is a signed decimal number that needs at least 16 bits. You're already telling the compiler what the lower bound is in how many bits to allocate to it, so it is okay for scanf
. This is also why we don't have a %ld
.
Please do correct me if I am wrong or inform me what I can do to make this answer better. I'm pretty sure it is not a perfect answer.
Upvotes: 0
Views: 1407
Reputation: 241961
See §6.5.2.2/6-7 in the C99 standard.
§6.5.2.2/6 defines the default argument promotions: (emphasis added)
the integer promotions are performed on each argument, and arguments that have type
float
are promoted todouble
.
and specifies that these promotions are performed on arguments to a function declared with no prototype (that is, with an empty parameter list ()
instead of (void)
, where the latter is used to indicate no arguments).
Paragraph 7 additionally specifies that if the prototype of the function has a trailing ellipsis (...):
The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
The integer promotions are defined in §6.3.1.1/2; they apply to
objects or expressions of an integer type whose "integer conversion rank is less than or equal to the rank of int
and unsigned int
": roughly speaking, any smaller integer type, such as boolean or character types;
bit-fields of type _Bool
, int
, signed int
or unsigned int
.
If an
int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions.All other types are unchanged by the integer promotions.
In short, if you have varargs function, such as printf
or scanf
:
Integer arguments which are no larger than int
are converted to (possibly unsigned) int
. (This does not include long
.)
Floating point arguments which are no larger than double
are converted to double
. (This includes float
.)
Pointers are unaltered.
Other non-pointer types are unaltered.
So printf
doesn't need to distinguish between float
and double
, because it will never be passed a float
. It does need to distinguish between int
and long
.
But scanf
does need to know whether an argument is a pointer to a float
or a pointer to a double
, because pointers are unchanged by the default argument promotions.
Upvotes: 1
Reputation: 497
You can think scanf as converting input stream into variables that defined in your code. Thus, scanf needs to know the exactly size for each variable. In general, the 32-bit and 64-bit IEEE 754 binary floating-point formats are used in C. So, %f means 32-bit and %lf means 64-bit.
Besides %ld exists and it means 32-bit integer. %lld also exists which means 64-bit integer. The above wiki site explains all C data types very well.
Upvotes: 2