Bit shifting past length of type

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

    #1

    Bit shifting past length of type

    Is it a defined operation when I do something like this:
    char a = 15;
    a = a<<9;
  • Richard Heathfield

    #2
    Re: Bit shifting past length of type

    British0zzy said:
    Is it a defined operation when I do something like this:
    char a = 15;
    a = a<<9;
    Only on systems where char has at least 10 bits.

    The relevant Standard cite is 3.3.7 Bitwise shift operators:

    "If the value of the right operand is negative or is greater than or equal
    to the width in bits of the promoted left operand, the behavior is
    undefined."

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

    • British0zzy

      #3
      Re: Bit shifting past length of type

      Richard Heathfield wrote:
      British0zzy said:
      >
      Is it a defined operation when I do something like this:
      char a = 15;
      a = a<<9;
      >
      Only on systems where char has at least 10 bits.
      >
      The relevant Standard cite is 3.3.7 Bitwise shift operators:
      >
      "If the value of the right operand is negative or is greater than or equal
      to the width in bits of the promoted left operand, the behavior is
      undefined."
      Is there any system out there which will not zero out all the bits?


      Comment

      • Peter Nilsson

        #4
        Re: Bit shifting past length of type

        Richard Heathfield <r...@see.sig.i nvalidwrote:
        British0zzy said:
        Is it a defined operation when I do something like
        this:
        char a = 15;
        a = a<<9;
        >
        Only on systems where char has at least 10 bits.
        >
        The relevant Standard cite is 3.3.7 Bitwise shift
        operators:
        >
        "If the value of the right operand is negative or is
        greater than or equal to the width in bits of the
        promoted left operand, the behavior is undefined."
        ^^^^^^^^

        That is almost incidental. The promoted type must have
        a width of at least 16.

        The problem is that plain char may be signed or
        otherwise promote to a narrow int.

        n1256: 6.5.7p4

        The result of E1 << E2 is E1 left-shifted E2 bit
        positions; vacated bits are filled with zeros. ...
        If E1 has a signed type and nonnegative value,
        and E1x2^E2 is representable in the result type,
        then that is the resulting value; otherwise, the
        behavior is undefined.

        If CHAR_MAX == INT_MAX, then even a shift of 1
        could invoke undefined behaviour.

        There is also a problem with the assignment if the
        shifted value _is_ representable as an int, but
        outside the range of plain char.

        Neither C90 nor C99 guarantee truncation for narrowing
        of signed types. Under C99, an implementation defined
        signal may even be raised.

        As disasterous as this all sounds, the solution
        is very simple. Where possible, stick to unsigned
        types for bitwise operations. It is rarely impractical
        to do this.

        --
        Peter

        Comment

        • Peter Nilsson

          #5
          Re: Bit shifting past length of type

          British0zzy <british0...@gm ail.comwrote:
          Richard Heathfield wrote:
          British0zzy said:
          Is it a defined operation when I do something like
          this:
          char a = 15;
          a = a<<9;
          >
          Is there any system out there which will not zero out
          all the bits?
          Why don't you state what you're trying to do, rather than
          asking if code which you _think_ is the solution to an
          (undisclosed problem) is valid?

          You should be shifting unsigned types where possible.
          It's unusual to shift wider than given type, but not
          that unusual to shift _as wide_ as the given type.

          If w is the width of an unsigned type, it's easy to
          shift by 0..w bits, where a shift of w zeros out the
          field...

          /* shift by n bits: 0 <= n <= width of u */
          if (w) u = u << (n - 1) << 1;

          Note that 'width' means the number of (sign plus)
          value bits, not necessarily the full size of the
          type in bits.

          --
          Peter

          Comment

          • Eric Sosman

            #6
            Re: Bit shifting past length of type

            British0zzy wrote:
            Richard Heathfield wrote:
            >British0zzy said:
            >>
            >>Is it a defined operation when I do something like this:
            >>char a = 15;
            >>a = a<<9;
            >Only on systems where char has at least 10 bits.
            The value of CHAR_BIT doesn't matter, not directly. The
            expression is evaluated this way:

            - First, the starting value of `a' is converted from `char'
            to `int' (on most systems) or `unsigned int' (on some).
            The statement is now equivalent to one of `a = 15 << 9;'
            or `a = 15u << 9;'.

            - Next, the shift operator is applied. The numerical result
            is within the range of both `int' and `unsigned int', so
            now we have either `a = 7680;' or `a = 7680u;'.

            - Now comes the dodgy part: The result of the shift is
            converted from `int' or `unsigned int' to `char'. If
            If `char' is unsigned, all is well: the conversion
            yields `7680 % (CHAR_MAX+1)', mathematically speaking.
            If `char' is signed and if CHAR_MAX >= 7680 (implying
            CHAR_BIT >= 14), all is well again and the conversion
            yields `(char)7680'. It's the remaining case that makes
            trouble: if `char' is signed and CHAR_MAX < 7680, the
            conversion takes us into poorly-charted waters, either
            yielding an implementation-defined result or raising an
            implementation-defined signal.

            - Finally (if we get this far), the converted value is
            stored in `a'.

            So, yes: The value of CHAR_BIT affects the outcome because
            it affects the value of CHAR_MAX used in the conversion, but it
            does not affect the operation of or validity of the shift. To
            illustrate, changing the second line to `int i = a << 9;' yields
            a fragment whose behavior is the same on all implementations .

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

            Comment

            • Peter Nilsson

              #7
              Re: Bit shifting past length of type

              Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
              British0zzy said:
              >char a = 15;
              >a = a<<9;
              >
              ...The value of CHAR_BIT affects the outcome because
              it affects the value of CHAR_MAX used in the conversion,
              but it does not affect the operation of or validity of
              the shift.
              >
              ... changing the second line to `int i = a << 9;'
              yields a fragment whose behavior is the same on all
              implementations .
              If CHAR_MAX <= INT_MAX and a (INT_MAX >9), then the
              behaviour of a << 9 is undefined.

              --
              Peter

              Comment

              • CBFalconer

                #8
                Re: Bit shifting past length of type

                British0zzy wrote:
                >
                Is it a defined operation when I do something like this:
                char a = 15;
                a = a<<9;
                That depends on the value of MAX_CHAR. Compare it with 512 * 15.

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

                Comment

                • blargg

                  #9
                  Re: Bit shifting past length of type

                  In article
                  <f8aa0754-b029-4b88-909d-1829e884a737@k7 g2000hsd.google groups.com>, Peter
                  Nilsson <airia@acay.com .auwrote:

                  [...]
                  If w is the width of an unsigned type, it's easy to
                  shift by 0..w bits, where a shift of w zeros out the
                  field...
                  >
                  /* shift by n bits: 0 <= n <= width of u */
                  if (w) u = u << (n - 1) << 1;
                  >
                  Note that 'width' means the number of (sign plus)
                  value bits, not necessarily the full size of the
                  type in bits.
                  Even though the comment claims that n can be 0, the code causes UB for n=0
                  due to n-1. Even if the n-1 issue is solved, you still have the
                  unconditional shift left by 1 to deal with. How about something like

                  int halfn = n >1;
                  u << halfn << (n-halfn)

                  which then allows n to be up to w*2-1?

                  Comment

                  • Peter Nilsson

                    #10
                    Re: Bit shifting past length of type

                    CBFalconer <cbfalco...@yah oo.comwrote:
                    British0zzy wrote:
                    Is it a defined operation when I do something like
                    this:
                      char a = 15;
                      a = a<<9;
                    >
                    That depends on the value of MAX_CHAR.
                    ITYM CHAR_MAX
                     Compare it with 512 * 15.
                    --
                    Peter

                    Comment

                    • Jack Klein

                      #11
                      Re: Bit shifting past length of type

                      On Wed, 1 Oct 2008 23:43:12 -0700 (PDT), Peter Nilsson
                      <airia@acay.com .auwrote in comp.lang.c:
                      Richard Heathfield <r...@see.sig.i nvalidwrote:
                      British0zzy said:
                      Is it a defined operation when I do something like
                      this:
                      char a = 15;
                      a = a<<9;
                      Only on systems where char has at least 10 bits.

                      The relevant Standard cite is 3.3.7 Bitwise shift
                      operators:

                      "If the value of the right operand is negative or is
                      greater than or equal to the width in bits of the
                      promoted left operand, the behavior is undefined."
                      ^^^^^^^^
                      >
                      That is almost incidental. The promoted type must have
                      a width of at least 16.
                      >
                      The problem is that plain char may be signed or
                      otherwise promote to a narrow int.
                      What exactly do you mean by "promote to a narrower int"? How can int
                      be narrower than int?

                      Did you mean "promote to a narrower integer type than int"? If so,
                      chapter and verse, please.

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

                      Comment

                      • Eric Sosman

                        #12
                        Re: Bit shifting past length of type

                        Peter Nilsson wrote:
                        Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
                        >>>British0zz y said:
                        >>>>char a = 15;
                        >>>>a = a<<9;
                        >...The value of CHAR_BIT affects the outcome because
                        >it affects the value of CHAR_MAX used in the conversion,
                        >but it does not affect the operation of or validity of
                        >the shift.
                        >>
                        >... changing the second line to `int i = a << 9;'
                        >yields a fragment whose behavior is the same on all
                        >implementation s.
                        >
                        If CHAR_MAX <= INT_MAX and a (INT_MAX >9), then the
                        behaviour of a << 9 is undefined.
                        Yes. But since INT_MAX is at least 32767, then
                        INT_MAX>>9 is at least 63, a number greater than the
                        value of `a'. The second half of your premise never
                        holds, so the conclusion does not apply.

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

                        Comment

                        • Peter Nilsson

                          #13
                          Re: Bit shifting past length of type

                          Jack Klein <jackkl...@spam cop.netwrote:
                          Peter Nilsson <ai...@acay.com .auwrote in comp.lang.c:
                          Richard Heathfield <r...@see.sig.i nvalidwrote:
                          British0zzy said:
                          Is it a defined operation when I do something like
                          this:
                          char a = 15;
                          a = a<<9;
                          >
                          Only on systems where char has at least 10 bits.
                          >
                          The relevant Standard cite is 3.3.7 Bitwise shift
                          operators:
                          >
                          "If the value of the right operand is negative or is
                          greater than or equal to the width in bits of the
                          promoted left operand, the behavior is undefined."
                            ^^^^^^^^
                          That is almost incidental. The promoted type must have
                          a width of at least 16.

                          The problem is that plain char may be signed or
                          otherwise promote to a narrow int.
                          >
                          What exactly do you mean by "promote to a narrower int"?
                          Since I didn't write that, I can't answer you. :-)

                          What I mean by 'narrow int' is that if plain char promotes
                          to int, then int must be at least 9 bits wider than plain
                          char for a left shift of 9 bits to be guaranteed to work
                          work for arbitrary char values. [Obviously, there is still
                          the problem of assigning the shifted value back to char.]

                          --
                          Peter

                          Comment

                          Working...