unwanted implicit casts

A

Andrew

Hello,

Is there anyway to detect when scanf implicitly casts a value? If I
have a scanf call which expects a float and is passed a double I
believe that testing the scanf call with if(scanf("%f",&val) == 1)
would be true, but the double would have been truncated to a float. Is
there anyway to flag this cast? Thanks
 
I

Ivan Vecerina

Hi,
Andrew said:
Is there anyway to detect when scanf implicitly casts a value? If I
have a scanf call which expects a float and is passed a double I
believe that testing the scanf call with if(scanf("%f",&val) == 1)
would be true, but the double would have been truncated to a float. Is
there anyway to flag this cast? Thanks

No. Calls to printf/scanf, unfortunately, are not type-safe.
However, some compilers can help, and will verify the matching
of a format string with the type of the actual parameters.

So one has to be extra careful with these functions.
( C++ provides increased safety here, with its streaming
operations: cin >> val; will always behave correctly,
regardless of the type of val... )

Regards,
 
R

Richard Heathfield

Andrew said:
Hello,

Is there anyway to detect when scanf implicitly casts a value? If I
have a scanf call which expects a float and is passed a double I
believe that testing the scanf call with if(scanf("%f",&val) == 1)
would be true, but the double would have been truncated to a float.

Firstly, scanf never expects a float. It can certainly expect a pointer to a
float. To give it a pointer to double in that circumstance is an error.

Secondly, there is no such thing as an implicit cast. Casts are, by
definition, explicit conversions.
 
A

Andrew

Richard Heathfield said:
Firstly, scanf never expects a float. It can certainly expect a pointer to a
float. To give it a pointer to double in that circumstance is an error.

Secondly, there is no such thing as an implicit cast. Casts are, by
definition, explicit conversions.

Thanks. I understand that passing a pointer to a double to scanf when
it expects a pointer to a float would be an error, but even if in the
example above val is declared type float won't the call to scanf
truncate any value entered to a float? For instance if I have the
following code snippet

unsigned int num;

printf("\nEnter number: ");
scanf("%i",&num);

printf("\nThe answer is: %i\n", num);

If on a 32 bit machine the user enters 4294967300 The answer printed
would be 4? Will errno be set to ERANGE? I can not see that it is. Or
is there some other way to test that this overflow condition occured?
Thanks
 
C

Chris Torek

... I understand that passing a pointer to a double to scanf when
it expects a pointer to a float would be an error, but even if in the
example above val is declared type float won't the call to scanf
truncate any value entered to a float? For instance if I have the
following code snippet

unsigned int num;

printf("\nEnter number: ");
scanf("%i",&num);

printf("\nThe answer is: %i\n", num);

If on a 32 bit machine the user enters 4294967300 The answer printed
would be 4? Will errno be set to ERANGE? I can not see that it is. Or
is there some other way to test that this overflow condition occured?

The scanf() function family should in general not be used on
"non-sanitized" input. (Certain formats can be used, especially
if you are Dan Pop :) , on certain streams with reasonable
safety.)

In particular, scanning 4294967300 with %i format gives undefined
behavior. In *my* stdio, the %i conversion actually uses strtol(),
so that you will get 2147483647 on a 32-bit-int machine with errno
set to ERANGE. (Note that %i expects a pointer to a *signed* int,
not an unsigned one.) On other systems, however, you will indeed
get the result described above.

If you have the sequence "4294967300" (including terminating '\0'
character) in an array, however, you can write:

unsigned long result;

result = strtoul(that_array, NULL, 10);

to force a base-10 conversion of the numeric value, with clamping
at ULONG_MAX. (Set base to 0 for a %i-like prefix-determines-base
conversion.) Note that strtoul() allows leading "-" prefixes;
if you wish to prohibit those, you must check the input yourself.

Reading arbitrary user input is one of the most difficult things
to do in C, or indeed in many other languages. The problem is not
so much the language -- although C often makes it unusually easy
to get something wrong here -- but rather with the fact that humans
find such inventive ways to present your program with unexpected
input. For instance, the five-year-old might hold down the 'b'
key (or drop a sausage on it) until it has repeated several hundred
thousand times.
 
J

Jack Klein

Thanks. I understand that passing a pointer to a double to scanf when
it expects a pointer to a float would be an error, but even if in the
example above val is declared type float won't the call to scanf
truncate any value entered to a float? For instance if I have the
following code snippet

unsigned int num;

printf("\nEnter number: ");
scanf("%i",&num);

printf("\nThe answer is: %i\n", num);

If on a 32 bit machine the user enters 4294967300 The answer printed
would be 4? Will errno be set to ERANGE? I can not see that it is. Or
is there some other way to test that this overflow condition occured?
Thanks

On what 32 bit machine? Did you think there was only one?

As far as this group is concerned, the result doesn't matter since the
behavior is undefined.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,206
Latest member
Zenden

Latest Threads

Top