Type conversion question

Discussion in 'C Programming' started by 1230987za@gmail.com, Aug 16, 2007.

  1. Guest

    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?
    , Aug 16, 2007
    #1
    1. Advertising

  2. 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?
    christian.bau, Aug 16, 2007
    #2
    1. Advertising

  3. 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) <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"
    Keith Thompson, Aug 16, 2007
    #3
  4. Dan Mills Guest

    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.
    Dan Mills, Aug 16, 2007
    #4
  5. 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.
    Ben Bacarisse, Aug 16, 2007
    #5
  6. Guest

    On Aug 15, 6:00 pm, "christian.bau" <>
    wrote:
    > 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.
    , Aug 16, 2007
    #6
  7. 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?
    Martin Ambuhl, Aug 16, 2007
    #7
  8. Richard Guest

    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.
    Richard, Aug 16, 2007
    #8
  9. Richard Bos Guest

    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
    Richard Bos, Aug 16, 2007
    #9
  10. Richard Guest

    (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


    --
    Richard, Aug 16, 2007
    #10
  11. Richard Bos Guest

    Richard <> wrote:

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


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

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


    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
    Richard Bos, Aug 16, 2007
    #11
  12. Richard Guest

    (Richard Bos) writes:

    > Richard <> wrote:
    >
    >> (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.

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

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

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

    >
    > Richard


    --
    Richard, Aug 16, 2007
    #12
  13. Richard <> writes:
    > Martin Ambuhl <> writes:

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

    [...]

    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.

    --
    Keith Thompson (The_Other_Keith) <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"
    Keith Thompson, Aug 16, 2007
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. luna
    Replies:
    1
    Views:
    6,802
  2. ibiza
    Replies:
    2
    Views:
    5,331
    ibiza
    Jan 27, 2006
  3. Chris
    Replies:
    2
    Views:
    21,324
    Chris
    May 11, 2006
  4. Michal Nazarewicz

    conversion from const type* to type* allowed?

    Michal Nazarewicz, Jan 4, 2007, in forum: C Programming
    Replies:
    13
    Views:
    550
    Eric Sosman
    Jan 5, 2007
  5. Replies:
    1
    Views:
    442
    Sylvester Hesp
    May 16, 2007
Loading...

Share This Page