Code problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jacob navia

    #1

    Code problem

    I posted this to comp.std.c, but may be of interest here too:

    Consider this:

    extern void abort(void);
    int main (void)
    {
    unsigned long long xx;
    unsigned long long *x = (unsigned long long *) &xx;

    *x = -3;
    *x = *x * *x;
    if (*x != 9)
    abort ();
    return(0);
    }

    lcc-win interprets
    *x = -3;
    as
    *x = 4294967293;
    since x points to an UNSIGNED long long.
    I cast the 32 bit integer -3 into an unsigned integer
    then I cast the result to an unsigned long long.

    Apparently gcc disagrees.

    Am I doing something wrong somewhere?

    I should first cast into a long long THEN into an unsigned
    long long?

    Thanks for your help.

    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
  • Ben Pfaff

    #2
    Re: Code problem

    jacob navia <jacob@nospam.c omwrites:
    int main (void)
    {
    unsigned long long xx;
    unsigned long long *x = (unsigned long long *) &xx;
    Why the cast? It should be unnecessary.
    *x = -3;
    *x = *x * *x;
    if (*x != 9)
    abort ();
    return(0);
    }
    >
    lcc-win interprets
    *x = -3;
    as
    *x = 4294967293;
    since x points to an UNSIGNED long long.
    unsigned long long has to be at least 64 bits in size.
    184467440737095 51613 is the minimum correct value for *x here.
    I cast the 32 bit integer -3 into an unsigned integer
    then I cast the result to an unsigned long long.
    I don't see any cast to unsigned int in the above program.
    --
    Ben Pfaff

    Comment

    • Richard Heathfield

      #3
      Re: Code problem

      jacob navia said:
      I posted this to comp.std.c, but may be of interest here too:
      >
      Consider this:
      >
      extern void abort(void);
      int main (void)
      {
      unsigned long long xx;
      unsigned long long *x = (unsigned long long *) &xx;
      Remove the unnecessary cast:

      unsigned long long *x = &xx;
      >
      *x = -3;
      See 6.2.5(9).
      *x = *x * *x;
      if (*x != 9)
      abort ();
      It is deeply unlikely that *x will be 9 at this point.
      return(0);
      }
      >
      lcc-win interprets
      *x = -3;
      as
      *x = 4294967293;
      since x points to an UNSIGNED long long.
      That's a bug in lcc-win. *x must have the value ULLONG_MAX - 2, and since
      ULLONG_MAX must be at least 184467440737095 51615, *x must be at least
      184467440737095 51613.
      I cast the 32 bit integer -3 into an unsigned integer
      then I cast the result to an unsigned long long.
      Why?
      Apparently gcc disagrees.
      >
      Am I doing something wrong somewhere?
      Yes. If your article is an accurate description of lcc-win's behaviour,
      your mistake is in using a non-conforming compiler.
      I should first cast into a long long THEN into an unsigned
      long long?
      No, there is almost certainly no need to cast anything at all. The first
      step is to identify the problem you are trying to solve, which is far from
      clear. If you want to know the result of multiplying -3 by -3, why use an
      unsigned type in the first place?

      --
      Richard Heathfield <http://www.cpax.org.uk >
      Email: -http://www. +rjh@
      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
      "Usenet is a strange place" - dmr 29 July 1999

      Comment

      • jameskuyper@verizon.net

        #4
        Re: Code problem

        jacob navia wrote:
        I posted this to comp.std.c, but may be of interest here too:
        >
        Consider this:
        >
        extern void abort(void);
        int main (void)
        {
        unsigned long long xx;
        unsigned long long *x = (unsigned long long *) &xx;
        >
        *x = -3;
        *x = *x * *x;
        if (*x != 9)
        abort ();
        return(0);
        }
        >
        lcc-win interprets
        *x = -3;
        as
        *x = 4294967293;
        since x points to an UNSIGNED long long.
        The minimum value for ULLONG_MAX is 184467440737095 51615, so you
        should be getting a value of at least 184467440737095 51613
        I cast the 32 bit integer -3 into an unsigned integer
        then I cast the result to an unsigned long long.
        Why did you do that?
        Apparently gcc disagrees.
        >
        Am I doing something wrong somewhere?
        Yes.
        I should first cast into a long long THEN into an unsigned
        long long?
        Why do you think that? Why are you using intermediaries?

        You should be converting -3 directly to unsigned long long. You should
        neither detour through unsigned int, nor detour through long long. The
        result should be ULLONG_MAX+1-3.

        Comment

        • Ben Pfaff

          #5
          Re: Code problem

          Richard Heathfield <rjh@see.sig.in validwrites:
          jacob navia said:
          > unsigned long long xx;
          > unsigned long long *x = (unsigned long long *) &xx;
          > *x = -3;
          > *x = *x * *x;
          > if (*x != 9)
          > abort ();
          >
          It is deeply unlikely that *x will be 9 at this point.
          2**64 - 3 == 184467440737095 51613
          (18446744073709 551613)**2 = 340282366920938 463352694142989 510901769
          340282366920938 463352694142989 510901769 % 2**64 = 9

          At least according to the calculator I have here.
          --
          int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
          \n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
          );while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
          );}return 0;}

          Comment

          • Eric Sosman

            #6
            Re: Code problem

            jacob navia wrote:
            I posted this to comp.std.c, but may be of interest here too:
            >
            Consider this:
            >
            extern void abort(void);
            int main (void)
            {
            unsigned long long xx;
            unsigned long long *x = (unsigned long long *) &xx;
            What is the cast for? (Hint: What is the type of
            the expression `&xx'?)
            *x = -3;
            *x = *x * *x;
            if (*x != 9)
            abort ();
            return(0);
            }
            >
            lcc-win interprets
            *x = -3;
            as
            *x = 4294967293;
            That cannot possibly be correct. ULLONG_MAX is at
            least 184467440737095 51615, so ULLONG_MAX-2 (the required
            result) is at least 184467440737095 51614.
            since x points to an UNSIGNED long long.
            I cast the 32 bit integer -3 into an unsigned integer
            then I cast the result to an unsigned long long.
            That would be correct iff ULLONG_MAX==ULO NG_MAX.

            Imagine converting a signed char to an unsigned long
            by the analogous route. Let's assume an 8-bit char, a
            16-bit int, and a 32-bit long (and because there's no
            way to write a literal of type char, I'll need to use
            a variable instead):

            signed char sc = -3;
            unsigned long ul = sc;

            The procedure you've outlined would convert sc to an
            unsigned int, getting 65533u, and then convert that value
            to unsigned long, yielding 65533ul. Yet the correct
            result is ULONG_MAX-2 == 4294967293. The intermediate
            conversion has lost sign information that affects the
            ultimate result.
            Apparently gcc disagrees.
            >
            Am I doing something wrong somewhere?
            >
            I should first cast into a long long THEN into an unsigned
            long long?
            You should convert the signed int to unsigned long long
            by adding or subtracting ULLONG_MAX+1 the appropriate number
            of times: in this case, by adding it once.

            --
            Eric.Sosman@sun .com

            Comment

            • jacob navia

              #7
              Re: Code problem

              Ben Pfaff wrote:
              jacob navia <jacob@nospam.c omwrites:
              >
              >int main (void)
              >{
              > unsigned long long xx;
              > unsigned long long *x = (unsigned long long *) &xx;
              >
              Why the cast? It should be unnecessary.
              >
              > *x = -3;
              > *x = *x * *x;
              > if (*x != 9)
              > abort ();
              > return(0);
              >}
              >>
              >lcc-win interprets
              > *x = -3;
              >as
              > *x = 4294967293;
              >since x points to an UNSIGNED long long.
              >
              unsigned long long has to be at least 64 bits in size.
              184467440737095 51613 is the minimum correct value for *x here.
              >
              >I cast the 32 bit integer -3 into an unsigned integer
              >then I cast the result to an unsigned long long.
              >
              I don't see any cast to unsigned int in the above program.
              Of course not. The casts were the result of loading a 32 bit constant
              and extending it to a 64 bit constant in assembly.

              I was missing the sign extend in the process.

              Conceptually however, what is
              (unsigned)-3

              ???

              supposing sizeof(int)=4
              sizeof(long long)=8

              -3 is 4294967293

              When you write "-3" that is a signed integer constant, in my system
              32 bits, i.e. the above number.

              When I do a sign extend, then it works
              --
              jacob navia
              jacob at jacob point remcomp point fr
              logiciels/informatique
              http://www.cs.virginia.edu/~lcc-win32

              Comment

              • jacob navia

                #8
                Re: Code problem

                Ben Pfaff wrote:
                Richard Heathfield <rjh@see.sig.in validwrites:
                >
                >jacob navia said:
                >> unsigned long long xx;
                >> unsigned long long *x = (unsigned long long *) &xx;
                >> *x = -3;
                >> *x = *x * *x;
                >> if (*x != 9)
                >> abort ();
                >It is deeply unlikely that *x will be 9 at this point.
                >
                2**64 - 3 == 184467440737095 51613
                (18446744073709 551613)**2 = 340282366920938 463352694142989 510901769
                340282366920938 463352694142989 510901769 % 2**64 = 9
                >
                At least according to the calculator I have here.
                Yes, it should be 9. I was missing a sign extend when
                converting a signed int into an unsigned long long.

                --
                jacob navia
                jacob at jacob point remcomp point fr
                logiciels/informatique
                http://www.cs.virginia.edu/~lcc-win32

                Comment

                • jacob navia

                  #9
                  Re: Code problem

                  jameskuyper@ver izon.net wrote:
                  jacob navia wrote:
                  >I posted this to comp.std.c, but may be of interest here too:
                  >>
                  >Consider this:
                  >>
                  >extern void abort(void);
                  >int main (void)
                  >{
                  > unsigned long long xx;
                  > unsigned long long *x = (unsigned long long *) &xx;
                  >>
                  > *x = -3;
                  > *x = *x * *x;
                  > if (*x != 9)
                  > abort ();
                  > return(0);
                  >}
                  >>
                  >lcc-win interprets
                  > *x = -3;
                  >as
                  > *x = 4294967293;
                  >since x points to an UNSIGNED long long.
                  >
                  The minimum value for ULLONG_MAX is 184467440737095 51615, so you
                  should be getting a value of at least 184467440737095 51613
                  >
                  >I cast the 32 bit integer -3 into an unsigned integer
                  >then I cast the result to an unsigned long long.
                  >
                  Why did you do that?
                  >
                  >Apparently gcc disagrees.
                  >>
                  >Am I doing something wrong somewhere?
                  >
                  Yes.
                  >
                  >I should first cast into a long long THEN into an unsigned
                  >long long?
                  >
                  Why do you think that? Why are you using intermediaries?
                  >
                  You should be converting -3 directly to unsigned long long. You should
                  neither detour through unsigned int, nor detour through long long. The
                  result should be ULLONG_MAX+1-3.
                  Yes, I was missing a sign extend.

                  But the abstract problem is still not clear to me. I mean when I see
                  a number like

                  -3

                  unadorned this is a signed integer constant. Since I am assigning it to
                  an unsigned value, I reinterpret the bits as an unsigned (this is my
                  mistake probably) and then convert THAT into an unsigned long long.


                  --
                  jacob navia
                  jacob at jacob point remcomp point fr
                  logiciels/informatique
                  http://www.cs.virginia.edu/~lcc-win32

                  Comment

                  • jacob navia

                    #10
                    Re: Code problem

                    Richard Heathfield wrote:
                    >Am I doing something wrong somewhere?
                    >
                    Yes. If your article is an accurate description of lcc-win's behaviour,
                    your mistake is in using a non-conforming compiler.
                    >
                    ????

                    Bugs are non conforming by definition...

                    :()

                    >I should first cast into a long long THEN into an unsigned
                    >long long?
                    >
                    No, there is almost certainly no need to cast anything at all. The first
                    step is to identify the problem you are trying to solve, which is far from
                    clear. If you want to know the result of multiplying -3 by -3, why use an
                    unsigned type in the first place?
                    >
                    Because that is part of a bigger program that I got
                    and I isolated (after some hours of debugging) the code
                    that exposes the bug in my software! (lcc-win)

                    I assure you that I know the multiplication tables, but thanks
                    for the answer anyway.

                    --
                    jacob navia
                    jacob at jacob point remcomp point fr
                    logiciels/informatique
                    http://www.cs.virginia.edu/~lcc-win32

                    Comment

                    • Richard Heathfield

                      #11
                      Re: Code problem

                      Ben Pfaff said:
                      Richard Heathfield <rjh@see.sig.in validwrites:
                      >
                      >It is deeply unlikely that *x will be 9 at this point.
                      >
                      2**64 - 3 == 184467440737095 51613
                      (18446744073709 551613)**2 = 340282366920938 463352694142989 510901769
                      340282366920938 463352694142989 510901769 % 2**64 = 9
                      I did the math before posting, and removed an entire paragraph about this
                      (further down the article), but evidently I omitted to remove the above
                      sentence. Oops, sorry etc.

                      --
                      Richard Heathfield <http://www.cpax.org.uk >
                      Email: -http://www. +rjh@
                      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                      "Usenet is a strange place" - dmr 29 July 1999

                      Comment

                      • Richard Heathfield

                        #12
                        Re: Code problem

                        Eric Sosman said:
                        ULLONG_MAX is at
                        least 184467440737095 51615, so ULLONG_MAX-2 (the required
                        result) is at least 184467440737095 51614.
                        ITYM 184467440737095 51613

                        --
                        Richard Heathfield <http://www.cpax.org.uk >
                        Email: -http://www. +rjh@
                        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                        "Usenet is a strange place" - dmr 29 July 1999

                        Comment

                        • Richard Tobin

                          #13
                          Re: Code problem

                          In article <fja0jo$u4u$3@a ioe.org>, jacob navia <jacob@nospam.o rgwrote:
                          >> unsigned long long xx;
                          >> unsigned long long *x = (unsigned long long *) &xx;
                          >>>
                          >> *x = -3;
                          >> *x = *x * *x;
                          >> if (*x != 9)
                          >> abort ();
                          Is there supposed to be any significance to using *x instead of xx?
                          The types of *x and xx are the same, so the same conversions should
                          apply.
                          >But the abstract problem is still not clear to me. I mean when I see
                          >a number like
                          >
                          >-3
                          >
                          >unadorned this is a signed integer constant.
                          Strictly speaking, there are no negative integer constants. The syntax
                          for integer constants doesn't allow minus signs. It's a constant
                          expression of type int (the result of applying unary minus to the
                          integer constant 3).
                          >Since I am assigning it to
                          >an unsigned value, I reinterpret the bits as an unsigned (this is my
                          >mistake probably) and then convert THAT into an unsigned long long.
                          Yes, this is your mistake. You have an int that you are assigning to
                          an unsigned long long, so you should do that conversion in a single
                          step.

                          The final answer will be 9 as your code implies, since the result of
                          the conversion will be equal to -3 (mod N), where log2(N) is the
                          number of bits in an unsigned long long, and if

                          a = A (mod N) and b = B (mod N)
                          then
                          a*b = A*B (mod N)

                          -- Richard
                          --
                          :wq

                          Comment

                          • Richard Tobin

                            #14
                            Re: Code problem

                            In article <fja0pv$u4u$4@a ioe.org>, jacob navia <jacob@nospam.o rgwrote:
                            >Bugs are non conforming by definition...
                            Not necessarily - a bug in code that implements undefined behaviour
                            just results in some other undefined behaviour, which is equally
                            conformant :-)

                            -- Richard
                            --
                            :wq

                            Comment

                            • Eric Sosman

                              #15
                              Re: Code problem

                              Richard Heathfield wrote:
                              Eric Sosman said:
                              >
                              >ULLONG_MAX is at
                              >least 184467440737095 51615, so ULLONG_MAX-2 (the required
                              >result) is at least 184467440737095 51614.
                              >
                              ITYM 184467440737095 51613
                              YTC.

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

                              Comment

                              Working...