Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Type conversion question

Reply
Thread Tools

Type conversion question

 
 
1230987za@gmail.com
Guest
Posts: n/a
 
      08-15-2007
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?

 
Reply With Quote
 
 
 
 
christian.bau
Guest
Posts: n/a
 
      08-16-2007
123098...@gmail.com wrote:
> 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?

 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      08-16-2007
writes:
> 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.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Dan Mills
Guest
Posts: n/a
 
      08-16-2007
On Wed, 15 Aug 2007 16:35:22 -0700, 1230987za wrote:


<Snip>

> 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:


<Snip>

> 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.
--
Nil coitus alto - seen above the door to a 11KV switchroom.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      08-16-2007
writes:

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


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

<snip>
> 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 <stdio.h> at the top or your program is wrong.

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

--
Ben.
 
Reply With Quote
 
1230987za@gmail.com
Guest
Posts: n/a
 
      08-16-2007
On Aug 15, 6:00 pm, "christian.bau" <christian....@cbau.wanadoo.co.uk>
wrote:
> 123098...@gmail.com wrote:
> > 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?


Sorry, my fault.

Please discard this post. I do have another question, will post
seperately.

 
Reply With Quote
 
Martin Ambuhl
Guest
Posts: n/a
 
      08-16-2007
wrote:
> 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?


 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      08-16-2007
Martin Ambuhl <> writes:

> wrote:
>> 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?


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.
 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      08-16-2007
Richard <> wrote:

> Martin Ambuhl <> writes:
>
> > wrote:


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


> >> 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?

>
> 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
 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      08-16-2007
(Richard Bos) writes:

> Richard <> wrote:
>
>> Martin Ambuhl <> writes:
>>
>> > wrote:

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

>
>> >> 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?

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


"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.

>
> Richard


--
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Type conversion function for user defined type... zaeminkr@gmail.com C++ 1 05-16-2007 09:00 AM
conversion from const type* to type* allowed? Michal Nazarewicz C Programming 13 01-05-2007 01:54 PM
Conversion from type 'DBNull' to type 'String' is not valid Chris ASP .Net 2 05-11-2006 08:20 AM
conversion from type 'DBNull' to type 'float' is not valid ibiza ASP .Net 2 01-27-2006 09:57 PM
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value. luna ASP .Net 1 02-13-2004 01:15 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57