Type conversion question

1

1230987za

Hi,
I am totally confused now about C type conversion.

I know that C does some implicit type conversion like integer
promotion and float to double. I imagine that such conversion must
keep the value through, meaning that the converted value equals to
their originals.

But the following code blew me away:

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);

return 0;
}

I had imagined the output is
ff=42.7
dd=42.7
dd1=43.7

But what I see is
ff=42.700001
dd=-1610612736
dd1=1078286745

Then I coded this test:

int main(){
int ii = 7;
char cc = (char) ii;
printf("cc=%c\n", cc);

cc = 7;
printf("cc=%i\n", cc);

union {
char c;
int i;
long l;
} u;

u.i = 7;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);

u.c = (char) u.i;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);


return 0;
}


I see this result:

cc=
cc=7
u.c=
u.l=7
u.c=
u.l=7

This is as I expected, but since I was so off by the first test,
could you confirm there is no compiler/OS dependent thing in the 2nd
test -- it should always output that result?

And how about the 1st test?
 
C

christian.bau

Hi,
I am totally confused now about C type conversion.

I know that C does some implicit type conversion like integer
promotion and float to double. I imagine that such conversion must
keep the value through, meaning that the converted value equals to
their originals.

But the following code blew me away:

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);

What is the format specifier for double values?
 
K

Keith Thompson

I am totally confused now about C type conversion.

I know that C does some implicit type conversion like integer
promotion and float to double. I imagine that such conversion must
keep the value through, meaning that the converted value equals to
their originals.

But the following code blew me away:

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);

return 0;
}

You need '#include <stdio.h>' at the top of the file. Calling printf
(or any other variadic function) with no prototype in scope invokes
undefined behavior. You're likely to get away with it, and it's
probably not the actual cause of your problem, but you should correct
it anyway.

Your real problem is that your format string is incorrect. The "%d"
format expects an argument of type int, not double (the 'd' stands for
"decimal"). And "%f" expects an argument of type double, but a float
argument is promoted to double (because printf is a variadic
function).

Try this:

#include <stdio.h>
int main(void)
{
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%f\ndd1=%f\n", ff, dd, dd1);
return 0;
}

[...]
Then I coded this test:

int main(){
int ii = 7;
char cc = (char) ii;

The cast is unnecessary; the value will be implicitly converted
without it.
printf("cc=%c\n", cc);

cc = 7;
printf("cc=%i\n", cc);

"%i" is equivalent to "%d", so this is ok. Most C programmers use
"%d" rather than "%i"; I'm not sure why "%i" is supported, but it is.
union {
char c;
int i;
long l;
} u;

u.i = 7;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);

u.c = (char) u.i;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);


return 0;
}

You're doing some dangerous stuff here. Storing a value in one member
of a union and then reading a different member invokes undefined
behavior. (There are exceptions for character types, but it's still
tricky.) In practice, after you've stored the value 7 in u.i, reading
u.c should give you the first byte of the int. The number of bytes in
an int, and the order in which they're stored, varies from one
implementation to another. Most likely you'll get either a null
character or an ASCII BEL character, but it's not guaranteed to be
either.
 
D

Dan Mills

On Wed, 15 Aug 2007 16:35:22 -0700, 1230987za wrote:


But the following code blew me away:

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);

return 0;
}

I had imagined the output is
ff=42.7
dd=42.7
dd1=43.7

But what I see is
ff=42.700001

42.7 is not exactly representable as a fp number.
dd=-1610612736
dd1=1078286745

Check your printf format specifiers (%d is not what you think)!
Then I coded this test:

union {
char c;
int i;
long l;
} u;

u.i = 7;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);

u.c = (char) u.i;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);


return 0;
}


I see this result:

cc=
cc=7
u.c=
u.l=7
u.c=
u.l=7

This is as I expected, but since I was so off by the first test,
could you confirm there is no compiler/OS dependent thing in the 2nd
test -- it should always output that result?

Again check the definitions of your printf format specifiers, I don't think
%c does quite what you expect.

Also I think the type punning in the union is either implementation or
undefined behaviour, but I don't have a copy of the standard to hand to
check.

HTH.

Regards, Dan.
 
B

Ben Bacarisse

Hi,
I am totally confused now about C type conversion.

No, you are confused about printf formats (and some other stuff).

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);

return 0;
}

I had imagined the output is
ff=42.7
dd=42.7
dd1=43.7

But what I see is
ff=42.700001
dd=-1610612736
dd1=1078286745

%d expects an int. You *must* include a prototype for printf or your
program exhibits the dreaded "undefined behaviour". Executive
translation: #include said:
Then I coded this test:

(BTW, This is not a good way to learn. There are books that just tell
you what various things in C do.)
int main(){
int ii = 7;
char cc = (char) ii;
printf("cc=%c\n", cc);

cc = 7;
printf("cc=%i\n", cc);

union {
char c;
int i;
long l;
} u;

u.i = 7;
printf("u.c=%c\n", u.c);

Undefined behaviour again. You've not been lurking have you? Only a
few moments ago there was a thread explaining that you can only
retrieve the value from that last member you assign to (u.i here).

There are portable ways to find out how things are represented in
memory. In fact, another recent thread discussed just that.
printf("u.l=%li\n", u.l);

u.c = (char) u.i;
printf("u.c=%c\n", u.c);
printf("u.l=%li\n", u.l);


return 0;
}


I see this result:

cc=
cc=7
u.c=
u.l=7
u.c=
u.l=7

This is as I expected, but since I was so off by the first test,
could you confirm there is no compiler/OS dependent thing in the 2nd
test -- it should always output that result?

What character is denoted by the integer value 7 is system dependant.
The other stuff is not permitted by the standard C so, technically,
anything can happen.
 
M

Martin Ambuhl

Hi,
I am totally confused now about C type conversion.

I know that C does some implicit type conversion like integer
promotion and float to double. I imagine that such conversion must
keep the value through, meaning that the converted value equals to
their originals.

But the following code blew me away:

int main(){
float ff = 42.7;
double dd = ff;
double dd1 = ff + 1.0;
printf("ff=%f\ndd=%d\ndd1=%d\n", ff, dd, dd1);
^^^^^ dd is not an int
^^^ dd1 is not an int
If you lie to printf, then you deserve the garbage it
will produce based on that lie.
return 0;
}

I had imagined the output is
ff=42.7
dd=42.7
dd1=43.7

Why in heave's name would you think that printf given the specifier %d,
which is for integers would
a) do anything "reasonable" with a floating point value?
b) print something that is impossible if is printing an integer?
 
R

Richard

Martin Ambuhl said:
^^^^^ dd is not an int
^^^ dd1 is not an int
If you lie to printf, then you deserve the garbage it
will produce based on that lie.


Why in heave's name would you think that printf given the specifier
%d, which is for integers would
a) do anything "reasonable" with a floating point value?

Quite obvious really. A lot of people MIGHT make the reasonable
assumption that the float would cast to an int and only the integer part
used.

e.g 3.4 -> 3

I don't think that is as ridiculous an assumption for a nOOb as you make
it sound.
b) print something that is impossible if is printing an integer?

That makes no sense.
 
R

Richard Bos

Richard said:
Quite obvious really. A lot of people MIGHT make the reasonable
assumption that the float would cast to an int and only the integer part
used.

For a cast, which is an explicit conversion, that would indeed be the
reasonable assumption - and it would be correct. But nowhere in the
above is there any cast, and there isn't even a conversion, neither
explicit nor implicit.
The only bit in the above which is even slightly surprising to a newbie
is that variadic functions do not automagically (try to) convert their
arguments to the desired type, as properly declared normal functions do;
but a moment's thought should make it clear that, in the absence of a
full declaration that can tell the implementation what kind of arguments
a variadic function expects, there is no magic that it _can_ do in such
cases, no more than for normal functions which are not fully declared.

Richard
 
R

Richard

For a cast, which is an explicit conversion, that would indeed be the
reasonable assumption - and it would be correct. But nowhere in the
above is there any cast, and there isn't even a conversion, neither
explicit nor implicit.

"would cast" - implicit.
The only bit in the above which is even slightly surprising to a newbie
is that variadic functions do not automagically (try to) convert their

Most newbies don't know what a variadic function is.
arguments to the desired type, as properly declared normal functions do;
but a moment's thought should make it clear that, in the absence of a
full declaration that can tell the implementation what kind of arguments
a variadic function expects, there is no magic that it _can_ do in such
cases, no more than for normal functions which are not fully declared.

I probably don't understand you, but I dont think I agree. It seems
relatively "obvious" (if incorrect) that some people would assume the
integer part is used.

--
 
R

Richard Bos

Richard said:
"would cast" - implicit.

Casts are explicit. A cast is something like this: (type). Conversions
can be implicit or explicit, but a cast is a piece of code.
Most newbies don't know what a variadic function is.

If someone isn't struck by the fact that some functions can be called
with a variable number of arguments, while most functions cannot, that
someone should not be a programmer. He doesn't have the natural
curiosity that is needed to solve problems.

Richard
 
R

Richard

Casts are explicit. A cast is something like this: (type). Conversions
can be implicit or explicit, but a cast is a piece of code.

Yes. I know. What part of "newbies assuming" seems to allude you?
If someone isn't struck by the fact that some functions can be called
with a variable number of arguments, while most functions cannot, that
someone should not be a programmer. He doesn't have the natural
curiosity that is needed to solve problems.

Err, right.

--
 
K

Keith Thompson

Richard said:
Quite obvious really. A lot of people MIGHT make the reasonable
assumption that the float would cast to an int and only the integer part
used.
[...]

My guess is that the OP thought "%d" is for double. Note that he used
"%i" for int (and "%f" for float). It's a silly misconception, but
easily corrected.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top