More bit shifting issues

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

    More bit shifting issues


    I seem to be having yet more wierd issue with bit shifting. It seems
    the following code doesnt do anything under gcc (ie it returns -1 as
    both results). Anyone know why? Is it another language definition or
    CPU issue?

    main()
    {
    printf("%d\n",( int)0xFFFFFFFF >1);
    printf("%d\n",( int)-1 >1);
    }

    B2003
  • Richard

    #2
    Re: More bit shifting issues

    Boltar <boltar2003@yah oo.co.ukwrites:
    I seem to be having yet more wierd issue with bit shifting. It seems
    the following code doesnt do anything under gcc (ie it returns -1 as
    both results). Anyone know why? Is it another language definition or
    CPU issue?
    >
    main()
    {
    printf("%d\n",( int)0xFFFFFFFF >1);
    printf("%d\n",( int)-1 >1);
    }
    >
    B2003
    Try using unsigned values and report back ...

    Comment

    • Richard Bos

      #3
      Re: More bit shifting issues

      Boltar <boltar2003@yah oo.co.ukwrote:
      printf("%d\n",( int)0xFFFFFFFF >1);
      printf("%d\n",( int)-1 >1);
      Right-shifting a negative value results in an implementation-defined
      value. As a first guess, your implementation does an arithmetic right
      shift where you expected a logical one. Both results are allowed.

      Richard

      Comment

      • Chris Dollin

        #4
        Re: More bit shifting issues

        Boltar wrote:
        >
        I seem to be having yet more wierd issue with bit shifting. It seems
        the following code doesnt do anything under gcc (ie it returns -1 as
        both results). Anyone know why? Is it another language definition or
        CPU issue?
        >
        main()
        {
        printf("%d\n",( int)0xFFFFFFFF >1);
        printf("%d\n",( int)-1 >1);
        }
        Shift-right of negative values is implementation-defined; you're likely
        to get one of arithmetic right shift or logical right shift. (Some machines
        have/had only one of these and would have to synthesise the other, which
        would be Woefully Inefficient.)

        It's wise to restrict ones bitwise operations to unsigned types, since
        these can't have tricksy sign bits to cut you with their nasty sharp
        edges.

        --
        "The whole apparatus had the look of having been put /Jack of Eagles/
        together with the most frantic haste a fanatically
        careful technician could muster."

        Hewlett-Packard Limited registered no:
        registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

        Comment

        • Martin Ambuhl

          #5
          Re: More bit shifting issues

          Boltar wrote:
          I seem to be having yet more wierd issue with bit shifting. It seems
          the following code doesnt do anything under gcc (ie it returns -1 as
          both results).
          It does something, namely to retain the signedness of your negative
          values. It didn't have to. It could have shifted in zeros instead of
          replicating the sign bit.
          Anyone know why? Is it another language definition or
          CPU issue?
          It is a mistake on your part. See the code below.
          main()
          {
          printf("%d\n",( int)0xFFFFFFFF >1);
          printf("%d\n",( int)-1 >1);
          }

          #include <stdio.h /* mha: needed for the variadic
          function printf */

          int /* mha: main returns an int, say so */ main(void)
          {
          printf("right shifting a negative value has no portably\n"
          "defined meaning, so the output of the next two\n"
          "printf statements is up for grabs:\n");
          printf(" ((int)0xFFFFFFF F >1) = %d\n", (int) 0xFFFFFFFF >1);
          printf(" ((int)-1 >) = %d\n\n", (int) -1 >1);
          printf("Note the difference in the following:\n");
          printf(" (0xFFFFFFFF >1) = %u\n", 0xFFFFFFFF >1);
          printf(" (int)(0xFFFFFFF F >1) = %d\n", (int) (0xFFFFFFFF >1));
          return 0; /* mha: even if you can get away
          without it, it is poor programming
          practice not to return a value from
          a function returning a value */
          }



          right shifting a negative value has no portably
          defined meaning, so the output of the next two
          printf statements is up for grabs:
          ((int)0xFFFFFFF F >1) = -1
          ((int)-1 >) = -1

          Note the difference in the following:
          (0xFFFFFFFF >1) = 2147483647
          (int)(0xFFFFFFF F >1) = 2147483647
          B2003

          Comment

          • Boltar

            #6
            Re: More bit shifting issues

            On Apr 1, 4:43 pm, "Bartc" <b...@freeuk.co mwrote:
            Right-shifting used to be an efficient way of dividing integer values by
            powers of two.
            But not any longer , any modern CPU has a div or mul type instruction.
            >
            The sign propagation is necessary to make it work with twos-complement
            negative numbers.
            So why don't the same rules apply to the &, | and ^ operators then?
            For example why doesn't (int)-1 ^ 0xFFFFFFFF still give -1 instead of
            zero?

            B2003

            Comment

            • Richard

              #7
              Re: More bit shifting issues

              Boltar <boltar2003@yah oo.co.ukwrites:
              On Apr 1, 4:43 pm, "Bartc" <b...@freeuk.co mwrote:
              >Right-shifting used to be an efficient way of dividing integer values by
              >powers of two.
              >
              But not any longer , any modern CPU has a div or mul type instruction.
              >
              >>
              >The sign propagation is necessary to make it work with twos-complement
              >negative numbers.
              >
              So why don't the same rules apply to the &, | and ^ operators then?
              For example why doesn't (int)-1 ^ 0xFFFFFFFF still give -1 instead of
              zero?
              >
              B2003
              Because its a bitwise operator and not a word operator. There is no
              notion of "sign" with single bits being or'd, and'ed or xor'ed.

              Comment

              • Keith Thompson

                #8
                Re: More bit shifting issues

                Boltar <boltar2003@yah oo.co.ukwrites:
                On Apr 1, 4:43 pm, "Bartc" <b...@freeuk.co mwrote:
                >Right-shifting used to be an efficient way of dividing integer values by
                >powers of two.
                >
                But not any longer , any modern CPU has a div or mul type instruction.
                Yes, but the div or mul instruction might still be slower than an
                equivalent shift. More to the point, modern compilers are capable of
                generating a shift instruction for multiplication or division by a
                power of 2, *if* it makes the code faster and *if* it can prove that
                the result is equivalent.

                --
                Keith Thompson (The_Other_Keit h) <kst-u@mib.org>
                Nokia
                "We must do something. This is something. Therefore, we must do this."
                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                Comment

                • Philip Potter

                  #9
                  Re: More bit shifting issues

                  Boltar wrote:
                  On Apr 1, 4:43 pm, "Bartc" <b...@freeuk.co mwrote:
                  >Right-shifting used to be an efficient way of dividing integer values by
                  >powers of two.
                  >
                  But not any longer , any modern CPU has a div or mul type instruction.
                  Not in the embedded world. The processor I work with most frequently has
                  only optional support for mul and div.

                  Comment

                  • CBFalconer

                    #10
                    Re: More bit shifting issues

                    Boltar wrote:
                    >
                    I seem to be having yet more wierd issue with bit shifting. It
                    seems the following code doesnt do anything under gcc (ie it
                    returns -1 as both results). Anyone know why? Is it another
                    language definition or CPU issue?
                    >
                    main() {
                    printf("%d\n",( int)0xFFFFFFFF >1);
                    printf("%d\n",( int)-1 >1);
                    }
                    I suspect this covers it:

                    6.5 Expressions

                    .... snip ...

                    [#4] Some operators (the unary operator ~, and the binary
                    operators <<, >>, &, ^, and |, collectively described as
                    bitwise operators) are required to have operands that have
                    integer type. These operators return values that depend on
                    the internal representations of integers, and have
                    implementation-defined and undefined aspects for signed
                    types.

                    --
                    [mail]: Chuck F (cbfalconer at maineline dot net)
                    [page]: <http://cbfalconer.home .att.net>
                    Try the download section.



                    --
                    Posted via a free Usenet account from http://www.teranews.com

                    Comment

                    • robertwessel2@yahoo.com

                      #11
                      Re: More bit shifting issues

                      On Apr 1, 11:08 am, Boltar <boltar2...@yah oo.co.ukwrote:
                      On Apr 1, 4:43 pm, "Bartc" <b...@freeuk.co mwrote:
                      >
                      Right-shifting used to be an efficient way of dividing integer values by
                      powers of two.
                      >
                      But not any longer , any modern CPU has a div or mul type instruction.

                      Not at all. IPF, and many RISCs, for example, do not have an integer
                      divide (or often an FP one either). They often support a divide
                      approximation instruction, which you then need to follow with a few
                      iterations of Newton-Raphson to actually generate a quotient.

                      In any event, left shifts are typically a fair bit faster than
                      multiplies (often several times), although there are CPUs with
                      exceptional fast multiplies and exceptionally slow shifters where
                      that's not true, and right shifts are invariably *much* faster than
                      actual divisions (often 20-50 times).

                      Comment

                      • Boltar

                        #12
                        Re: More bit shifting issues

                        On Apr 1, 11:58 pm, "robertwess...@ yahoo.com"
                        <robertwess...@ yahoo.comwrote:
                        In any event, left shifts are typically a fair bit faster than
                        multiplies (often several times), although there are CPUs with
                        exceptional fast multiplies and exceptionally slow shifters where
                        that's not true, and right shifts are invariably *much* faster than
                        actual divisions (often 20-50 times).
                        Well that begs the question of why the cpu integer div instruction
                        doesn't simply check the divisors least significant bit to see if its
                        set to zero (even) and if it is then use bit shifting to get the
                        result. Same for multiply.

                        B2003

                        Comment

                        • Bartc

                          #13
                          Re: More bit shifting issues


                          "Boltar" <boltar2003@yah oo.co.ukwrote in message
                          news:863943e8-19c6-4fa5-9c4d-6ff04b747d7d@s1 3g2000prd.googl egroups.com...
                          On Apr 1, 11:58 pm, "robertwess...@ yahoo.com"
                          <robertwess...@ yahoo.comwrote:
                          >In any event, left shifts are typically a fair bit faster than
                          >multiplies (often several times), although there are CPUs with
                          >exceptional fast multiplies and exceptionally slow shifters where
                          >that's not true, and right shifts are invariably *much* faster than
                          >actual divisions (often 20-50 times).
                          >
                          Well that begs the question of why the cpu integer div instruction
                          doesn't simply check the divisors least significant bit to see if its
                          set to zero (even) and if it is then use bit shifting to get the
                          result. Same for multiply.
                          Probably because it's a *lot* easier to have separate instructions for
                          shift, which are essential anyway. And it would have to check there is only
                          one bit set.

                          Anyway most cpus must have a shift-right-logical which does exactly what you
                          want. It's up to your C implementation whether that is invoked by
                          right-shifting an unsigned value.

                          --
                          Bart


                          Comment

                          Working...