简体   繁体   中英

Why can we use %d for both scanf and printf?

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.

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.

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 to double .

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 an int ; otherwise, it is converted to an unsigned 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM