Integer promotion and overflow

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Russell Shaw

    #1

    Integer promotion and overflow

    Hi,
    I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
    and long long ints are 64 bits.

    When i have:

    int num=9600;
    long long int reg=(long long)8000000000 00/(5000000*num);

    the denominator overflows and gives an incorrect answer: reg=1059


    With an extra cast:

    long long int reg=(long long)8000000000 00/((long long)5000000*nu m);

    i get: reg=16


    If the numerator is a long long int, should the denominator be
    automatically promoted to a long long int?
  • jacob navia

    #2
    Re: Integer promotion and overflow

    Russell Shaw wrote:[color=blue]
    > Hi,
    > I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
    > and long long ints are 64 bits.
    >
    > When i have:
    >
    > int num=9600;
    > long long int reg=(long long)8000000000 00/(5000000*num);
    >
    > the denominator overflows and gives an incorrect answer: reg=1059
    >
    >
    > With an extra cast:
    >
    > long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
    >
    > i get: reg=16
    >
    >
    > If the numerator is a long long int, should the denominator be
    > automatically promoted to a long long int?[/color]

    lcc-win32 gives the same answer as gcc. The problem is
    that the denomitar *is* converted to long long. The
    compiler does:

    long long int reg=(long long)8000000000 00/(long long)(5000000*n um);

    Neither gcc nor lcc-win32 realize that the denominator is an
    expression, converting each member to the highest rank type.

    Maybe there are compilers that clever, but I would not rely
    on it, and would add the cast.

    jacob

    Comment

    • Eric Sosman

      #3
      Re: Integer promotion and overflow

      Russell Shaw wrote:[color=blue]
      > Hi,
      > I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
      > and long long ints are 64 bits.
      >
      > When i have:
      >
      > int num=9600;
      > long long int reg=(long long)8000000000 00/(5000000*num);
      >
      > the denominator overflows and gives an incorrect answer: reg=1059
      >
      >
      > With an extra cast:
      >
      > long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
      >
      > i get: reg=16
      >
      >
      > If the numerator is a long long int, should the denominator be
      > automatically promoted to a long long int?[/color]

      Yes. But the denominator (in the first form) is itself
      the product of two factors of type `int', so it is calculated
      in `int' arithmetic. The product is too large for an `int',
      so it overflows and is chopped down to 32 bits (on your system;
      C itself doesn't guarantee what happens). Then the already-
      damaged value is promoted to `long long' for the division, but
      it's too late: the denominator is much smaller than intended,
      so the quotient comes out much too large.

      In the second form, the 5000000 term is converted to `long
      long' by the cast operator. The denominator is then the product
      of a `long long' and an `int', so `num' is converted to `long
      long' and the multiplication is carried out in `long long'
      arithmetic and does not overflow. Then the division takes
      place, and everything comes out as expected.

      A better way to write this would be to make the constants
      `long long' to begin with:

      long long int reg = 800000000000LL / (5000000LL * num);

      --
      Eric Sosman
      esosman@acm-dot-org.invalid

      Comment

      • Chris Croughton

        #4
        Re: Integer promotion and overflow

        On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
        <jacob@jacob.re mcomp.fr> wrote:
        [color=blue]
        > lcc-win32 gives the same answer as gcc. The problem is
        > that the denomitar *is* converted to long long. The
        > compiler does:
        >
        > long long int reg=(long long)8000000000 00/(long long)(5000000*n um);
        >
        > Neither gcc nor lcc-win32 realize that the denominator is an
        > expression, converting each member to the highest rank type.[/color]

        Nor should they, C is specified such that conversions occur only when
        they are forced because the types are dissimilar (or when forced with a
        cast). For instance:

        long long denom = 5000000 * num;

        will give the same overflow, because it is specified that 5000000*num is
        calculated and only then converted to a long long.
        [color=blue]
        > Maybe there are compilers that clever, but I would not rely
        > on it, and would add the cast.[/color]

        It would not be 'clever', it would be against the standard. There are
        other /languages/ which have the semantics the other way round, so that
        expression type is propagated left to right (Algol and Pascal, I
        believe, do that), but any C compiler must do the sub-expressions first
        and promote the types only when it is necessary because the other
        operand is a higher type.

        Chris C

        Comment

        • Keith Thompson

          #5
          Re: Integer promotion and overflow

          Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes:[color=blue]
          > I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
          > and long long ints are 64 bits.
          >
          > When i have:
          >
          > int num=9600;
          > long long int reg=(long long)8000000000 00/(5000000*num);
          >
          > the denominator overflows and gives an incorrect answer: reg=1059
          >
          > With an extra cast:
          >
          > long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
          >
          > i get: reg=16
          >
          > If the numerator is a long long int, should the denominator be
          > automatically promoted to a long long int?[/color]

          The evaluation of an expression is not affected by the context in
          which it appears. Think of expressions, including their
          subexpressions, as being evaluated bottom-up, not top-down.

          The right operand of the "/" operator is:

          (5000000*num)

          Each operand of the "*" is of type int, so it's an int-by-int
          multiplication yielding an int result. (It overflows, which invokes
          undefined behavior, which most likely shows up as discarding the
          high-order bits.) That int result then becomes the right operand of
          the "/" operator. The left operand of the "/" operator is (long
          long)8000000000 00, which is of type long long, so the right operand is
          promoted to long long -- but that promotion (to 64 bits) is done
          *after* the 32-bit multiplication.

          Since the overflow invokes undefined behavior, I suppose a
          sufficiently clever compiler could let the context affect the
          evaluation of (5000000*num), so the whole expression yields a
          mathematically correct result. But such cleverness doesn't really do
          you any favors, it merely masks your error.

          (There are languages in which the context of an expression affects its
          evaluation. C is not such a language.)

          You might prefer to use a suffix on the integer constants rather than
          casting them to long long:

          long long int reg=80000000000 0LL/(5000000LL*num) ;

          On the other hand, the cast uses the type name explicitly, so it might
          be considered clearer.

          --
          Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

          Comment

          • Keith Thompson

            #6
            Re: Integer promotion and overflow

            Chris Croughton <chris@keristor .net> writes:[color=blue]
            > On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
            > <jacob@jacob.re mcomp.fr> wrote:[/color]
            [...][color=blue][color=green]
            >> Maybe there are compilers that clever, but I would not rely
            >> on it, and would add the cast.[/color]
            >
            > It would not be 'clever', it would be against the standard.[/color]
            [...]

            As I mentioned in another thread, it wouldn't be against the standard
            if it affected the visible behavior of the program only when it
            invokes undefined behavior. But such "cleverness " would not be a good
            idea, since it would tend to mask errors.

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

            Comment

            • Keith Thompson

              #7
              Re: Integer promotion and overflow

              Keith Thompson <kst-u@mib.org> writes:[color=blue]
              > Chris Croughton <chris@keristor .net> writes:[color=green]
              >> On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
              >> <jacob@jacob.re mcomp.fr> wrote:[/color]
              > [...][color=green][color=darkred]
              >>> Maybe there are compilers that clever, but I would not rely
              >>> on it, and would add the cast.[/color]
              >>
              >> It would not be 'clever', it would be against the standard.[/color]
              > [...]
              >
              > As I mentioned in another thread, it wouldn't be against the standard
              > if it affected the visible behavior of the program only when it
              > invokes undefined behavior. But such "cleverness " would not be a good
              > idea, since it would tend to mask errors.[/color]

              Sorry, I meant to say "As I mentioned elsewhere in this thread ...".

              --
              Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

              Comment

              • Jack Klein

                #8
                Re: Integer promotion and overflow

                On Sun, 02 Jan 2005 23:03:44 GMT, Keith Thompson <kst-u@mib.org> wrote
                in comp.lang.c:
                [color=blue]
                > Chris Croughton <chris@keristor .net> writes:[color=green]
                > > On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
                > > <jacob@jacob.re mcomp.fr> wrote:[/color]
                > [...][color=green][color=darkred]
                > >> Maybe there are compilers that clever, but I would not rely
                > >> on it, and would add the cast.[/color]
                > >
                > > It would not be 'clever', it would be against the standard.[/color]
                > [...]
                >
                > As I mentioned in another thread, it wouldn't be against the standard
                > if it affected the visible behavior of the program only when it
                > invokes undefined behavior. But such "cleverness " would not be a good
                > idea, since it would tend to mask errors.[/color]

                True. But if either of the operands in the calculation of the
                denominator were unsigned, such 'early promotion' would be
                non-conforming.

                --
                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.l earn.c-c++

                Comment

                • Neo

                  #9
                  Re: Integer promotion and overflow


                  "Keith Thompson" <kst-u@mib.org> wrote in message
                  news:ln8y7bmpvu .fsf@nuthaus.mi b.org...[color=blue]
                  > Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes:[color=green]
                  >> I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
                  >> and long long ints are 64 bits.
                  >>
                  >> When i have:
                  >>
                  >> int num=9600;
                  >> long long int reg=(long long)8000000000 00/(5000000*num);
                  >>
                  >> the denominator overflows and gives an incorrect answer: reg=1059
                  >>
                  >> With an extra cast:
                  >>
                  >> long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
                  >>
                  >> i get: reg=16
                  >>
                  >> If the numerator is a long long int, should the denominator be
                  >> automatically promoted to a long long int?[/color]
                  >
                  > The evaluation of an expression is not affected by the context in
                  > which it appears. Think of expressions, including their
                  > subexpressions, as being evaluated bottom-up, not top-down.
                  >
                  > The right operand of the "/" operator is:
                  >
                  > (5000000*num)
                  >
                  > Each operand of the "*" is of type int, so it's an int-by-int
                  > multiplication yielding an int result. (It overflows, which invokes
                  > undefined behavior, which most likely shows up as discarding the
                  > high-order bits.) That int result then becomes the right operand of
                  > the "/" operator. The left operand of the "/" operator is (long
                  > long)8000000000 00, which is of type long long, so the right operand is
                  > promoted to long long -- but that promotion (to 64 bits) is done
                  > *after* the 32-bit multiplication.
                  >
                  > Since the overflow invokes undefined behavior, I suppose a
                  > sufficiently clever compiler could let the context affect the
                  > evaluation of (5000000*num), so the whole expression yields a
                  > mathematically correct result. But such cleverness doesn't really do
                  > you any favors, it merely masks your error.
                  >
                  > (There are languages in which the context of an expression affects its
                  > evaluation. C is not such a language.)
                  >
                  > You might prefer to use a suffix on the integer constants rather than
                  > casting them to long long:
                  >
                  > long long int reg=80000000000 0LL/(5000000LL*num) ;[/color]

                  Hi Keith,

                  I used the following form :

                  int num = 9600;
                  long long int i = (long long)8000000000 00/(5000000LL * num);
                  printf("%ld\n", i);

                  on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
                  longlong.c: In function `main':
                  longlong.c:7: warning: integer constant is too large for "long" type
                  output : 16

                  and to more surprise when compiling the same code on Solaris Workstation
                  with gcc 3.3 warning was the same as above but the result :
                  output : 0

                  WHY IT IS SO??????

                  Thanks n Regards
                  -Neo
                  [color=blue]
                  >
                  > On the other hand, the cast uses the type name explicitly, so it might
                  > be considered clearer.
                  >
                  > --
                  > Keith Thompson (The_Other_Keit h) kst-u@mib.org
                  > <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.[/color]


                  Comment

                  • Michael Mair

                    #10
                    Re: Integer promotion and overflow



                    Neo wrote:[color=blue]
                    > "Keith Thompson" <kst-u@mib.org> wrote in message
                    > news:ln8y7bmpvu .fsf@nuthaus.mi b.org...
                    >[color=green]
                    >>Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes:
                    >>[color=darkred]
                    >>>I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
                    >>>and long long ints are 64 bits.
                    >>>
                    >>>When i have:
                    >>>
                    >>> int num=9600;
                    >>> long long int reg=(long long)8000000000 00/(5000000*num);
                    >>>
                    >>>the denominator overflows and gives an incorrect answer: reg=1059
                    >>>
                    >>>With an extra cast:
                    >>>
                    >>> long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
                    >>>
                    >>>i get: reg=16
                    >>>
                    >>>If the numerator is a long long int, should the denominator be
                    >>>automaticall y promoted to a long long int?[/color]
                    >>
                    >>The evaluation of an expression is not affected by the context in
                    >>which it appears. Think of expressions, including their
                    >>subexpression s, as being evaluated bottom-up, not top-down.
                    >>
                    >>The right operand of the "/" operator is:
                    >>
                    >> (5000000*num)
                    >>
                    >>Each operand of the "*" is of type int, so it's an int-by-int
                    >>multiplicatio n yielding an int result. (It overflows, which invokes
                    >>undefined behavior, which most likely shows up as discarding the
                    >>high-order bits.) That int result then becomes the right operand of
                    >>the "/" operator. The left operand of the "/" operator is (long
                    >>long)80000000 0000, which is of type long long, so the right operand is
                    >>promoted to long long -- but that promotion (to 64 bits) is done
                    >>*after* the 32-bit multiplication.
                    >>
                    >>Since the overflow invokes undefined behavior, I suppose a
                    >>sufficientl y clever compiler could let the context affect the
                    >>evaluation of (5000000*num), so the whole expression yields a
                    >>mathematicall y correct result. But such cleverness doesn't really do
                    >>you any favors, it merely masks your error.
                    >>
                    >>(There are languages in which the context of an expression affects its
                    >>evaluation. C is not such a language.)
                    >>
                    >>You might prefer to use a suffix on the integer constants rather than
                    >>casting them to long long:
                    >>
                    >> long long int reg=80000000000 0LL/(5000000LL*num) ;[/color]
                    >
                    >
                    > Hi Keith,
                    >
                    > I used the following form :
                    >
                    > int num = 9600;
                    > long long int i = (long long)8000000000 00/(5000000LL * num);
                    > printf("%ld\n", i);
                    >
                    > on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
                    > longlong.c: In function `main':
                    > longlong.c:7: warning: integer constant is too large for "long" type
                    > output : 16
                    >
                    > and to more surprise when compiling the same code on Solaris Workstation
                    > with gcc 3.3 warning was the same as above but the result :
                    > output : 0
                    >
                    > WHY IT IS SO??????[/color]

                    RTFmanpage (printf):

                    The length modifier l specifies _long_, not _long_long_.
                    If you want to print a long long, use ll:
                    printf("%lld\n" , i);

                    Depending on the byte representation of the number in memory, we may
                    well arrive at 16 (korrekt) or 0, if erroneously reading only a part
                    of the bytes belonging to the argument.


                    Cheers
                    Michael
                    --
                    E-Mail: Mine is a gmx dot de address.

                    Comment

                    • Keith Thompson

                      #11
                      Re: Integer promotion and overflow

                      Jack Klein <jackklein@spam cop.net> writes:[color=blue]
                      > On Sun, 02 Jan 2005 23:03:44 GMT, Keith Thompson <kst-u@mib.org> wrote
                      > in comp.lang.c:
                      >[color=green]
                      >> Chris Croughton <chris@keristor .net> writes:[color=darkred]
                      >> > On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
                      >> > <jacob@jacob.re mcomp.fr> wrote:[/color]
                      >> [...][color=darkred]
                      >> >> Maybe there are compilers that clever, but I would not rely
                      >> >> on it, and would add the cast.
                      >> >
                      >> > It would not be 'clever', it would be against the standard.[/color]
                      >> [...]
                      >>
                      >> As I mentioned in another thread, it wouldn't be against the standard[/color][/color]
                      [correction: elsewhere in this thread][color=blue][color=green]
                      >> if it affected the visible behavior of the program only when it
                      >> invokes undefined behavior. But such "cleverness " would not be a good
                      >> idea, since it would tend to mask errors.[/color]
                      >
                      > True. But if either of the operands in the calculation of the
                      > denominator were unsigned, such 'early promotion' would be
                      > non-conforming.[/color]

                      Agreed (because unsigned overflow doesn't invoke undefined behavior
                      (which you know, of course, but others reading this may not)).

                      --
                      Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

                      Comment

                      • Neo

                        #12
                        Re: Integer promotion and overflow


                        "Michael Mair" <Michael.Mair@i nvalid.invalid> wrote in message
                        news:33s645F40i 738U1@individua l.net...[color=blue]
                        >
                        >
                        > Neo wrote:[color=green]
                        >> "Keith Thompson" <kst-u@mib.org> wrote in message
                        >> news:ln8y7bmpvu .fsf@nuthaus.mi b.org...
                        >>[color=darkred]
                        >>>Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes:
                        >>>
                        >>>>I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
                        >>>>and long long ints are 64 bits.
                        >>>>
                        >>>>When i have:
                        >>>>
                        >>>> int num=9600;
                        >>>> long long int reg=(long long)8000000000 00/(5000000*num);
                        >>>>
                        >>>>the denominator overflows and gives an incorrect answer: reg=1059
                        >>>>
                        >>>>With an extra cast:
                        >>>>
                        >>>> long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
                        >>>>
                        >>>>i get: reg=16
                        >>>>
                        >>>>If the numerator is a long long int, should the denominator be
                        >>>>automatical ly promoted to a long long int?
                        >>>
                        >>>The evaluation of an expression is not affected by the context in
                        >>>which it appears. Think of expressions, including their
                        >>>subexpressio ns, as being evaluated bottom-up, not top-down.
                        >>>
                        >>>The right operand of the "/" operator is:
                        >>>
                        >>> (5000000*num)
                        >>>
                        >>>Each operand of the "*" is of type int, so it's an int-by-int
                        >>>multiplicati on yielding an int result. (It overflows, which invokes
                        >>>undefined behavior, which most likely shows up as discarding the
                        >>>high-order bits.) That int result then becomes the right operand of
                        >>>the "/" operator. The left operand of the "/" operator is (long
                        >>>long)8000000 00000, which is of type long long, so the right operand is
                        >>>promoted to long long -- but that promotion (to 64 bits) is done
                        >>>*after* the 32-bit multiplication.
                        >>>
                        >>>Since the overflow invokes undefined behavior, I suppose a
                        >>>sufficient ly clever compiler could let the context affect the
                        >>>evaluation of (5000000*num), so the whole expression yields a
                        >>>mathematical ly correct result. But such cleverness doesn't really do
                        >>>you any favors, it merely masks your error.
                        >>>
                        >>>(There are languages in which the context of an expression affects its
                        >>>evaluation . C is not such a language.)
                        >>>
                        >>>You might prefer to use a suffix on the integer constants rather than
                        >>>casting them to long long:
                        >>>
                        >>> long long int reg=80000000000 0LL/(5000000LL*num) ;[/color]
                        >>
                        >>
                        >> Hi Keith,
                        >>
                        >> I used the following form :
                        >>
                        >> int num = 9600;
                        >> long long int i = (long long)8000000000 00/(5000000LL * num);
                        >> printf("%ld\n", i);
                        >>
                        >> on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
                        >> longlong.c: In function `main':
                        >> longlong.c:7: warning: integer constant is too large for "long" type
                        >> output : 16
                        >>
                        >> and to more surprise when compiling the same code on Solaris Workstation
                        >> with gcc 3.3 warning was the same as above but the result :
                        >> output : 0
                        >>
                        >> WHY IT IS SO??????[/color]
                        >
                        > RTFmanpage (printf):
                        >
                        > The length modifier l specifies _long_, not _long_long_.
                        > If you want to print a long long, use ll:
                        > printf("%lld\n" , i);
                        >
                        > Depending on the byte representation of the number in memory, we may
                        > well arrive at 16 (korrekt) or 0, if erroneously reading only a part
                        > of the bytes belonging to the argument.[/color]

                        Michael, thanks for the correction. It should be obviously "%lld\n".
                        But why the warning??? its still there.
                        [color=blue]
                        >
                        >
                        > Cheers
                        > Michael
                        > --
                        > E-Mail: Mine is a gmx dot de address.
                        >[/color]


                        Comment

                        • Keith Thompson

                          #13
                          Re: Integer promotion and overflow

                          "Neo" <timeless_illus ion@yahoo.com> writes:
                          [...][color=blue]
                          > I used the following form :
                          >
                          > int num = 9600;
                          > long long int i = (long long)8000000000 00/(5000000LL * num);
                          > printf("%ld\n", i);
                          >
                          > on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
                          > longlong.c: In function `main':
                          > longlong.c:7: warning: integer constant is too large for "long" type
                          > output : 16[/color]

                          In C99, the type of an unsuffixed decimal integer constant is the
                          first of int, long int, or long long int in which its value can be
                          represented.

                          In C90, there is no type long long int, so the constant is of type
                          long int (which is too small).

                          I think gcc is acting as a C90 compiler as far as determining the
                          types of integer constants is concerned, but is supporting long long
                          as an extension.

                          Try invoking gcc with "-std=c99" and/or use 800000000000LL rather than
                          (long long)8000000000 00.
                          [color=blue]
                          > and to more surprise when compiling the same code on Solaris Workstation
                          > with gcc 3.3 warning was the same as above but the result :
                          > output : 0[/color]

                          Because you're trying to print a long long value, but you're telling
                          printf to expect a long ("%ld"). Use "%lld" to print a long long.

                          --
                          Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

                          Comment

                          • aegis

                            #14
                            Re: Integer promotion and overflow


                            Eric Sosman wrote:[color=blue]
                            > Russell Shaw wrote:[color=green]
                            > > Hi,
                            > > I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32[/color][/color]
                            bits[color=blue][color=green]
                            > > and long long ints are 64 bits.
                            > >
                            > > When i have:
                            > >
                            > > int num=9600;
                            > > long long int reg=(long long)8000000000 00/(5000000*num);
                            > >
                            > > the denominator overflows and gives an incorrect answer: reg=1059
                            > >
                            > >
                            > > With an extra cast:
                            > >
                            > > long long int reg=(long long)8000000000 00/((long[/color][/color]
                            long)5000000*nu m);[color=blue][color=green]
                            > >
                            > > i get: reg=16
                            > >
                            > >
                            > > If the numerator is a long long int, should the denominator be
                            > > automatically promoted to a long long int?[/color]
                            >
                            > Yes. But the denominator (in the first form) is itself
                            > the product of two factors of type `int', so it is calculated
                            > in `int' arithmetic.[/color]

                            It would seem that 6.4.4.1#5 says that if 5000000 cannot be
                            represented by the type int then it would try long int
                            and if not long int, then long long int.

                            "The type of an integer constant is the first of the
                            corresponding list in which its value can be represented."

                            Atleast, that is how I interpreted it. The table follows with

                            Suffix Decimal Constant
                            none int
                            long int
                            long long int
                            hopefully google does not ruin my formatting

                            --
                            aegis

                            Comment

                            • Russell Shaw

                              #15
                              Re: Integer promotion and overflow

                              Neo wrote:[color=blue]
                              > "Michael Mair" <Michael.Mair@i nvalid.invalid> wrote in message
                              > news:33s645F40i 738U1@individua l.net...
                              >[color=green]
                              >>
                              >>Neo wrote:
                              >>[color=darkred]
                              >>>"Keith Thompson" <kst-u@mib.org> wrote in message
                              >>>news:ln8y7bm pvu.fsf@nuthaus .mib.org...
                              >>>[/color][/color][/color]

                              ....
                              [color=blue][color=green][color=darkred]
                              >>>Hi Keith,
                              >>>
                              >>>I used the following form :
                              >>>
                              >>>int num = 9600;
                              >>>long long int i = (long long)8000000000 00/(5000000LL * num);
                              >>>printf("%ld\ n", i);
                              >>>
                              >>>on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
                              >>>longlong.c : In function `main':
                              >>>longlong.c:7 : warning: integer constant is too large for "long" type
                              >>>output : 16
                              >>>
                              >>>and to more surprise when compiling the same code on Solaris Workstation
                              >>>with gcc 3.3 warning was the same as above but the result :
                              >>>output : 0
                              >>>
                              >>>WHY IT IS SO??????[/color]
                              >>
                              >>RTFmanpage (printf):
                              >>
                              >>The length modifier l specifies _long_, not _long_long_.
                              >>If you want to print a long long, use ll:
                              >>printf("%lld\ n", i);
                              >>
                              >>Depending on the byte representation of the number in memory, we may
                              >>well arrive at 16 (korrekt) or 0, if erroneously reading only a part
                              >>of the bytes belonging to the argument.[/color]
                              >
                              >
                              > Michael, thanks for the correction. It should be obviously "%lld\n".
                              > But why the warning??? its still there.[/color]

                              I get that warning in gcc-3.4.3 on linux too.

                              Comment

                              Working...