Integer promotion

Discussion in 'C Programming' started by Spoon, Sep 11, 2007.

  1. Spoon

    Spoon Guest

    Consider the following program:

    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    int main(int argc, char **argv)
    {
    uint32_t a = strtoul(argv[1], 0, 0);
    uint32_t b = strtoul(argv[2], 0, 0);
    double d = a-b;
    printf("%f\n", d);
    return 0;
    }

    $ ./a.out 5 6
    4294967295.000000

    This is what I expected.
    Since a-b would be negative, the result is a-b+2^32.

    However, if I replace uint32_t with uint16_t:

    $ ./a.out 5 6
    -1.000000

    I expected 65535 (-1+2^16).

    I suppose I'm forgetting some integer promotion rule?

    Is the simple fix just to write:

    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    int main(int argc, char **argv)
    {
    uint16_t a = strtoul(argv[1], 0, 0);
    uint16_t b = strtoul(argv[2], 0, 0);
    uint16_t diff = a-b;
    double d = diff;
    printf("%f\n", d);
    return 0;
    }

    Regards.
     
    Spoon, Sep 11, 2007
    #1
    1. Advertising

  2. Spoon

    Jack Klein Guest

    On Tue, 11 Sep 2007 17:56:04 +0200, Spoon <root@localhost> wrote in
    comp.lang.c:

    > Consider the following program:
    >
    > #include <stdint.h>
    > #include <stdlib.h>
    > #include <stdio.h>
    > int main(int argc, char **argv)
    > {
    > uint32_t a = strtoul(argv[1], 0, 0);
    > uint32_t b = strtoul(argv[2], 0, 0);
    > double d = a-b;
    > printf("%f\n", d);
    > return 0;
    > }
    >
    > $ ./a.out 5 6
    > 4294967295.000000
    >
    > This is what I expected.
    > Since a-b would be negative, the result is a-b+2^32.
    >
    > However, if I replace uint32_t with uint16_t:
    >
    > $ ./a.out 5 6
    > -1.000000
    >
    > I expected 65535 (-1+2^16).


    Why? Assuming that int has more than 16 bits on your platform, the
    values of both 'a' and 'b' are promoted to signed int before the
    addition, and the signed int result is then converted to double and
    assigned to 'd'.

    > I suppose I'm forgetting some integer promotion rule?
    >
    > Is the simple fix just to write:
    >
    > #include <stdint.h>
    > #include <stdlib.h>
    > #include <stdio.h>
    > int main(int argc, char **argv)
    > {
    > uint16_t a = strtoul(argv[1], 0, 0);
    > uint16_t b = strtoul(argv[2], 0, 0);
    > uint16_t diff = a-b;
    > double d = diff;
    > printf("%f\n", d);
    > return 0;
    > }
    >
    > Regards.


    Integer types narrower (of lesser rank) than int are always promoted
    to int or unsigned int when used as operands of expressions. The
    rules for this promotion from unsigned types of lesser rank than int
    are:

    -- if signed int can hold all the possible values of the lesser rank
    unsigned type, the value is promoted to signed int.

    -- if signed int cannot hold all the possible values of the lesser
    rank unsigned type, the value is promoted to unsigned int.

    So if you build and execute this program on a platform where int has
    16 bits, the values in 'a' and 'b' would promote to unsigned int and
    produced the result you expected. Since int on your platform has more
    than 16 bits, the values in 'a' and 'b' promoted to signed int and
    produced the result you saw.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Sep 11, 2007
    #2
    1. Advertising

  3. Spoon

    ¬a\\/b Guest

    On Tue, 11 Sep 2007 17:56:04 +0200, Spoon <root@localhost> wrote:

    >Consider the following program:
    >
    >#include <stdint.h>
    >#include <stdlib.h>
    >#include <stdio.h>
    >int main(int argc, char **argv)
    >{
    > uint32_t a = strtoul(argv[1], 0, 0);
    > uint32_t b = strtoul(argv[2], 0, 0);
    > double d = a-b;

    ^^^^^^^^^^^^^^^^^^^^^^^

    double d = (double)a-b;


    > printf("%f\n", d);
    > return 0;
    >}
    >
    >$ ./a.out 5 6
    >4294967295.00000
     
    ¬a\\/b, Sep 11, 2007
    #3
    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. Ray
    Replies:
    4
    Views:
    1,495
    Jack Klein
    Jan 6, 2004
  2. Russell Shaw

    Integer promotion and overflow

    Russell Shaw, Jan 2, 2005, in forum: C Programming
    Replies:
    20
    Views:
    1,093
    Keith Thompson
    Jan 3, 2005
  3. promotion of integer types

    , Mar 26, 2005, in forum: C Programming
    Replies:
    3
    Views:
    327
  4. Frederick Gotham

    Integer Promotion?

    Frederick Gotham, Jun 9, 2006, in forum: C Programming
    Replies:
    21
    Views:
    733
    Peter Boettcher
    Jun 28, 2006
  5. Replies:
    1
    Views:
    558
    christian.bau
    Jan 15, 2007
Loading...

Share This Page