Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   printf() and scanf() questions (http://www.velocityreviews.com/forums/t596334-printf-and-scanf-questions.html)

 Ioannis Vranos 03-05-2008 08:10 PM

printf() and scanf() questions

printf() questions:

1. printf() provides "%f" format specifier for double. Usually
implemented as a variadic function how can it discern if the argument is
float or double? Shouldn't we cast to double when passing a float value?
If an implicit conversion takes place, at what stage does it take place?
Consider as an example:

printf("%f\n", 123.45F);

2. The same question also applies when printing a signed char value with
"%d" format specifier.

scanf() questions:

1. scanf() provides the "%f" specifier for float. How can it discern
when we pass a double?

Example:

double x;

scanf("%f", &x);

If an implicit conversion to double takes place, at what stage does it
take place? Also if such conversion takes place how it works when using
a float variable?

Example:

float b;

scanf("%f", &b);

 Walter Roberson 03-05-2008 08:20 PM

Re: printf() and scanf() questions

In article <fqmunj\$2pcv\$1@ulysses.noc.ntua.gr>,
Ioannis Vranos <ivranos@nospam.no.spamfreemail.gr> wrote:

>printf() questions:

>1. printf() provides "%f" format specifier for double. Usually
>implemented as a variadic function how can it discern if the argument is
>float or double? Shouldn't we cast to double when passing a float value?
>If an implicit conversion takes place, at what stage does it take place?
>Consider as an example:

>printf("%f\n", 123.45F);

My first reaction upon reading this was "Homework!". But I know you
from other groups so I know you would not do that to us.

The answer is that for functions that do not have a prototype, and
the non-prototyped positions of varadic function calls, the
values passed *always* undergo "the usual argument promotions".
Those promote any passed (single precision) float to double,
-before- the receiving function sees it. The compiler knows to do
this promotion because it knows what the type of the actual argument
is, and it knows that it is handing it to a varadic or non-prototyped
function.

>scanf() questions:
>
>1. scanf() provides the "%f" specifier for float. How can it discern
>when we pass a double?

%f indicates floating point in general, not the type 'float'.
If you are supplying a pointer to a float, you use "%hf".
If you are supplying a pointer to a double, you use "%f".
If you are supplying a pointer to a long double, you use "%Lf".
--
What will be your last contribution?
-- Supertramp (Fool's Overture)

 Martin Ambuhl 03-05-2008 08:50 PM

Re: printf() and scanf() questions

Ioannis Vranos wrote:

> 1. printf() provides "%f" format specifier for double. Usually
> implemented as a variadic function

printf is always a variadic function.

> how can it discern if the argument is
> float or double?

The float argument, following the normal rules for arguments, is
promoted to a double. Both float and double arguments are presented to
printf as doubles.

> Shouldn't we cast to double when passing a float value?

No.

> 2. The same question also applies when printing a signed char value with
> "%d" format specifier.

The answer is analogous, and you should look in the index of your
elementary C text for something like "usual arithmetic conversions". If
an expression appears as an argument in a function call not governed by
a prototype, or when the expression appears as an argument in the
...." part of a prototype, the default function conversions are the same
as (C89 or C90) the usual arithmetic conversions or (C99) the unsual
unitary conversions except float is always promoted to double.
>
> scanf() questions:
>
> 1. scanf() provides the "%f" specifier for float. How can it discern
> when we pass a double?

You don'r ever pass scanf a double (unless you want it to fail). You
pass an address which the "%f" tells printf to interpret as a
pointer-to-float. If you want it to treat it as a pointer-to-double use
"%lf". This should be adequately covered in any elementary introduction
to C. The rest of your questions depend on your mistaken idea that you
are passing floats or doubles as arguments.

 Richard Tobin 03-05-2008 09:17 PM

Re: printf() and scanf() questions

In article <638fbrF2628fdU1@mid.individual.net>,

>> 1. printf() provides "%f" format specifier for double. Usually
>> implemented as a variadic function

>printf is always a variadic function.

Presumably by "implemented as a variadic function" the OP meant
implemented in the same way as user-defined variadic functions,
i.e. with stdarg.

If you look back in this group, you will find several posts claiming
that the *printf() functions don't have to work that way, and that you
can't therefore pass a char * for %p.

-- Richard
--
:wq

 Andrey Tarasevich 03-05-2008 09:21 PM

Re: printf() and scanf() questions

Ioannis Vranos wrote:
> printf() questions:
>
> 1. printf() provides "%f" format specifier for double. Usually
> implemented as a variadic function how can it discern if the argument is
> float or double?

There's no need to discern that. 'float' arguments that correspond to
'...' parameters are implicitly promoted and passed as 'double' parameters.

> Shouldn't we cast to double when passing a float value?

No, the promotion will do it implicitly.

> If an implicit conversion takes place, at what stage does it take place?

At the stage when the parameter list for the future function call is formed.

> 2. The same question also applies when printing a signed char value with
> "%d" format specifier.

The same thing happens, except the 'int' type is used as the target type
for the implicit promotion.

>
> scanf() questions:
>
> 1. scanf() provides the "%f" specifier for float. How can it discern
> when we pass a double?

We don't ever pass a 'double' to 'scanf'. We pass either 'float*' or
'double*'. (I hope you understand the difference between a 'double' and
a 'double*'). 'float*' and 'double*' are two different unrelated pointer
types. When we pass a 'float*' (for '%f'), it is passed and processed
internally as as a 'float*'. When we pass a 'double*' (for '%lf'), it is
passed and processed internally as 'double*'. That's it.

> If an implicit conversion to double takes place, at what stage does it
> take place?

There's no possibility for any implicit conversion here. Especially for
a "conversion to double".

--
Best regards,
Andrey Tarasevich

 Andrey Tarasevich 03-05-2008 09:33 PM

Re: printf() and scanf() questions

Walter Roberson wrote:
>>
>> 1. scanf() provides the "%f" specifier for float. How can it discern
>> when we pass a double?

>
> %f indicates floating point in general, not the type 'float'.
> If you are supplying a pointer to a float, you use "%hf".
> If you are supplying a pointer to a double, you use "%f".
> If you are supplying a pointer to a long double, you use "%Lf".

I haven't checked the very-very latest changes in the standard, but I
don't believe they can be that drastic. In the original edition of C99

- 'h' cannot be used in '%f'
- '%f' takes a 'float*' argument, '%lf' takes a 'double*' argument

--
Best regards,
Andrey Tarasevich

 Micah Cowan 03-05-2008 09:35 PM

Re: printf() and scanf() questions

roberson@ibd.nrc-cnrc.gc.ca (Walter Roberson) writes:

> In article <fqmunj\$2pcv\$1@ulysses.noc.ntua.gr>,
> Ioannis Vranos <ivranos@nospam.no.spamfreemail.gr> wrote:

>
>>printf() questions:

>
>>1. printf() provides "%f" format specifier for double. Usually
>>implemented as a variadic function how can it discern if the argument is
>>float or double? Shouldn't we cast to double when passing a float value?
>>If an implicit conversion takes place, at what stage does it take place?
>>Consider as an example:

>
>>printf("%f\n", 123.45F);

>
> My first reaction upon reading this was "Homework!". But I know you
> from other groups so I know you would not do that to us.
>
> The answer is that for functions that do not have a prototype, and
> the non-prototyped positions of varadic function calls, the
> values passed *always* undergo "the usual argument promotions".
> Those promote any passed (single precision) float to double,
> -before- the receiving function sees it. The compiler knows to do
> this promotion because it knows what the type of the actual argument
> is, and it knows that it is handing it to a varadic or non-prototyped
> function.

Note that all of this applies to variadic functions in C++ (where
Ioannis frequents) as well; and so in particular std::printf() can be
depended upon to work the same way there (at least in this
respect). Likewise for promotion of, say, char and unsigned char to
int (when sizeof(int) != 1; else unsigned char would be promoted to
unsigned int [in both C and C++]).

>>scanf() questions:
>>
>>1. scanf() provides the "%f" specifier for float. How can it discern
>>when we pass a double?

>
> %f indicates floating point in general, not the type 'float'.
> If you are supplying a pointer to a float, you use "%hf".
> If you are supplying a pointer to a double, you use "%f".
> If you are supplying a pointer to a long double, you use "%Lf".

Er, no. %f takes a float, %lf takes a double, and %Lf takes a long
double. The 'h' length modifier is used to specify (signed or
unsigned) short int only.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/

 Ioannis Vranos 03-05-2008 10:22 PM

Re: printf() and scanf() questions

Walter Roberson wrote:
> In article <fqmunj\$2pcv\$1@ulysses.noc.ntua.gr>,
> Ioannis Vranos <ivranos@nospam.no.spamfreemail.gr> wrote:
>> The questions are about C95.

>
>> printf() questions:

>
>> 1. printf() provides "%f" format specifier for double. Usually
>> implemented as a variadic function how can it discern if the argument is
>> float or double? Shouldn't we cast to double when passing a float value?
>> If an implicit conversion takes place, at what stage does it take place?
>> Consider as an example:

>
>> printf("%f\n", 123.45F);

>
> My first reaction upon reading this was "Homework!". But I know you
> from other groups so I know you would not do that to us.

Not a homework. I am actually revisiting my C95 knowledge, while I have
been using the more convenient C++ I/O facilities with the overloaded
member functions for all types for some time.

> The answer is that for functions that do not have a prototype, and
> the non-prototyped positions of varadic function calls, the
> values passed *always* undergo "the usual argument promotions".

I am not sure what you mean by this. #include <stdio.h> is assumed in my
printf() code and I am not using the implicit C function declaration stuff.

From this sentence of yours: "non-prototyped positions of varadic
function calls," I assume you mean the "..." stuff. Here is why I
wonder. Inside the definition of a variadic function we define the "type
step" of va_arg, based on an assumed input type, so if we expect double
we do:

[va_list curr_item;

double curr_val;
... ]

curr_val= va_arg(curr_item, double);

so if we pass a float and %f is about double, we will use the above
expression, with the wrong "step type".

> Those promote any passed (single precision) float to double,
> -before- the receiving function sees it. The compiler knows to do
> this promotion because it knows what the type of the actual argument
> is, and it knows that it is handing it to a varadic or non-prototyped
> function.
>
>
>> scanf() questions:
>>
>> 1. scanf() provides the "%f" specifier for float. How can it discern
>> when we pass a double?

>
> %f indicates floating point in general, not the type 'float'.

What does this "in general" mean? Works for both float and double? My
(Greek) K&R2 mentions (translated) that

"e, f, g floating point number; float *. ...."

> If you are supplying a pointer to a float, you use "%hf".
> If you are supplying a pointer to a double, you use "%f".
> If you are supplying a pointer to a long double, you use "%Lf".

Also my C99 (although off topic since I am talking about C95) mentions

"h Specifies that a following d, i, o, u, x, X, or n conversion
specifier applies to an argument with type pointer to short int or
unsigned short int.241)".

I do not think "%hf" for scanf() was in C90/C95 and has been removed
from C99, also with K&R 2 mentioning "%f" is for float *.

 Ioannis Vranos 03-05-2008 10:22 PM

Re: printf() and scanf() questions

Walter Roberson wrote:
> In article <fqmunj\$2pcv\$1@ulysses.noc.ntua.gr>,
> Ioannis Vranos <ivranos@nospam.no.spamfreemail.gr> wrote:
>> The questions are about C95.

>
>> printf() questions:

>
>> 1. printf() provides "%f" format specifier for double. Usually
>> implemented as a variadic function how can it discern if the argument is
>> float or double? Shouldn't we cast to double when passing a float value?
>> If an implicit conversion takes place, at what stage does it take place?
>> Consider as an example:

>
>> printf("%f\n", 123.45F);

>
> My first reaction upon reading this was "Homework!". But I know you
> from other groups so I know you would not do that to us.

Not a homework. I am actually revisiting my C95 knowledge, while I have
been using the more convenient C++ I/O facilities with the overloaded
member functions for all types for some time.

> The answer is that for functions that do not have a prototype, and
> the non-prototyped positions of varadic function calls, the
> values passed *always* undergo "the usual argument promotions".

I am not sure what you mean by this. #include <stdio.h> is assumed in my
printf() code and I am not using the implicit C function declaration stuff.

From this sentence of yours: "non-prototyped positions of variadic
function calls," I assume you mean the "..." stuff. Here is why I
wonder. Inside the definition of a variadic function we define the "type
step" of va_arg, based on an assumed input type, so if we expect double
we do:

[va_list curr_item;

double curr_val;
... ]

curr_val= va_arg(curr_item, double);

so if we pass a float and %f is about double, we will use the above
expression, with the wrong "step type".

> Those promote any passed (single precision) float to double,
> -before- the receiving function sees it. The compiler knows to do
> this promotion because it knows what the type of the actual argument
> is, and it knows that it is handing it to a varadic or non-prototyped
> function.
>
>
>> scanf() questions:
>>
>> 1. scanf() provides the "%f" specifier for float. How can it discern
>> when we pass a double?

>
> %f indicates floating point in general, not the type 'float'.

What does this "in general" mean? Works for both float and double? My
(Greek) K&R2 mentions (translated) that

"e, f, g floating point number; float *. ...."

> If you are supplying a pointer to a float, you use "%hf".
> If you are supplying a pointer to a double, you use "%f".
> If you are supplying a pointer to a long double, you use "%Lf".

Also my C99 (although off topic since I am talking about C95) mentions

"h Specifies that a following d, i, o, u, x, X, or n conversion
specifier applies to an argument with type pointer to short int or
unsigned short int.241)".

I do not think "%hf" for scanf() was in C90/C95 and has been removed
from C99, also with K&R 2 mentioning "%f" is for float *.

 Ioannis Vranos 03-05-2008 10:25 PM

Re: printf() and scanf() questions

Micah Cowan wrote:
>>> scanf() questions:
>>>
>>> 1. scanf() provides the "%f" specifier for float. How can it discern
>>> when we pass a double?

>> %f indicates floating point in general, not the type 'float'.
>> If you are supplying a pointer to a float, you use "%hf".
>> If you are supplying a pointer to a double, you use "%f".
>> If you are supplying a pointer to a long double, you use "%Lf".

>
> Er, no. %f takes a float, %lf takes a double, and %Lf takes a long
> double. The 'h' length modifier is used to specify (signed or
> unsigned) short int only.

You got my scanf() question answered: I did not remember that there was
a separate specifier for double, the "%lf", I thought "%f" was for both.

All times are GMT. The time now is 03:32 AM.