Bitshifting independant of signedness

Discussion in 'C Programming' started by Frederick Gotham, Aug 24, 2006.

  1. Just wondering if bitwise operators pay any attention to the signedness of
    an integer type? Do they pay any attention to, or work any differently
    with, the sign-bit, or with a signed integer type?

    Let's take a hypothetical system where:

    (1) int is comprised of 32 value bits (inclusive of the sign-bit).
    (2) Two's complement is used.

    The bit-pattern for -18 on such a system is:

    1111 1111 1111 1111 1111 1111 1110 1110

    On such a system is the following *guaranteed* to work?

    #define VALBITS_INT 31
    /* The above figure does NOT
    inlude the sign bit. */

    int Minus18()
    {
    int i = 0;

    /* (1) First set the sign-bit: */

    i |= 1U << VALBITS_INT;
    /* Will this definitely set the sign-bit?
    Is the U tag necessary on the literal? */

    /* (2) Set all other bits to 1: */

    int const MSBonly = 1 << VALBITS_INT-1;

    i |= MSBonly | MSBonly-1;

    /* (3) Toggle first and fifth bits */

    i ^= 1;
    i ^= 16;

    return i;
    }

    When performing a bitwise operation, are the integer types treated as if
    they're unsigned?

    --

    Frederick Gotham
    Frederick Gotham, Aug 24, 2006
    #1
    1. Advertising

  2. Frederick Gotham

    Michael Mair Guest

    Frederick Gotham schrieb:
    > Just wondering if bitwise operators pay any attention to the signedness of
    > an integer type? Do they pay any attention to, or work any differently
    > with, the sign-bit, or with a signed integer type?
    >
    > Let's take a hypothetical system where:
    >
    > (1) int is comprised of 32 value bits (inclusive of the sign-bit).
    > (2) Two's complement is used.

    (3) You assume that there are no padding bits in signed int
    that are not also there in unsigned int.
    (4) You assume that INT_MAX+1U != 0 (the "and vice versa"
    part for (3))

    > The bit-pattern for -18 on such a system is:
    >
    > 1111 1111 1111 1111 1111 1111 1110 1110
    >
    > On such a system is the following *guaranteed* to work?
    >
    > #define VALBITS_INT 31
    > /* The above figure does NOT
    > inlude the sign bit. */
    >
    > int Minus18()
    > {
    > int i = 0;
    >
    > /* (1) First set the sign-bit: */
    >
    > i |= 1U << VALBITS_INT;
    > /* Will this definitely set the sign-bit?
    > Is the U tag necessary on the literal? */


    Depends. The 1U will be detrimental if (4) does not hold as
    you would then shift "too far".

    >
    > /* (2) Set all other bits to 1: */
    >
    > int const MSBonly = 1 << VALBITS_INT-1;
    >
    > i |= MSBonly | MSBonly-1;


    Will not set all bits if (3) does not hold.
    i = ~0;
    certainly works better in that respect.

    >
    > /* (3) Toggle first and fifth bits */
    >
    > i ^= 1;
    > i ^= 16;
    >
    > return i;
    > }
    >
    > When performing a bitwise operation, are the integer types treated as if
    > they're unsigned?


    No. Note that you could "assemble" the representation and then
    reinterpret it:
    int i;
    unsigned int u = -1;
    unsigned neg = 18;
    u ^= (neg - 1U);
    i = *(int *)&u;
    This needs (1) to (4) as well.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Aug 24, 2006
    #2
    1. Advertising

  3. Frederick Gotham

    pete Guest

    Frederick Gotham wrote:
    >
    > Just wondering if bitwise operators pay any attention to the signedness of
    > an integer type? Do they pay any attention to, or work any differently
    > with, the sign-bit, or with a signed integer type?
    >
    > Let's take a hypothetical system where:
    >
    > (1) int is comprised of 32 value bits (inclusive of the sign-bit).
    > (2) Two's complement is used.
    >
    > The bit-pattern for -18 on such a system is:
    >
    > 1111 1111 1111 1111 1111 1111 1110 1110
    >
    > On such a system is the following *guaranteed* to work?
    >
    > #define VALBITS_INT 31
    > /* The above figure does NOT
    > inlude the sign bit. */
    >
    > int Minus18()
    > {
    > int i = 0;
    >
    > /* (1) First set the sign-bit: */
    >
    > i |= 1U << VALBITS_INT;
    > /* Will this definitely set the sign-bit?
    > Is the U tag necessary on the literal? */


    I think your attempt is undefined.

    >
    > /* (2) Set all other bits to 1: */
    >
    > int const MSBonly = 1 << VALBITS_INT-1;
    >
    > i |= MSBonly | MSBonly-1;
    >
    > /* (3) Toggle first and fifth bits */
    >
    > i ^= 1;
    > i ^= 16;
    >
    > return i;
    > }
    >
    > When performing a bitwise operation,
    > are the integer types treated as if
    > they're unsigned?


    No.

    Setting the sign bit with a left shift, looks undefined to me.

    N869
    6.5.7 Bitwise shift operators

    [#4] The result of E1 << E2 is E1 left-shifted E2 bit
    positions; vacated bits are filled with zeros. If E1 has an
    unsigned type, the value of the result is E1×2E2, reduced
    modulo one more than the maximum value representable in the
    result type. If E1 has a signed type and nonnegative value,
    and E1×2E2 is representable in the result type, then that is
    the resulting value; otherwise, the behavior is undefined.

    --
    pete
    pete, Aug 25, 2006
    #3
  4. Michael Mair posted:

    > (3) You assume that there are no padding bits in signed int
    > that are not also there in unsigned int.


    I said it had 32 value bits, not 32 object bits.

    --

    Frederick Gotham
    Frederick Gotham, Aug 25, 2006
    #4
  5. Frederick Gotham

    Michael Mair Guest

    Frederick Gotham schrieb:
    > Michael Mair posted:
    >
    >> (3) You assume that there are no padding bits in signed int
    >> that are not also there in unsigned int.

    >
    > I said it had 32 value bits, not 32 object bits.


    Yes. However, only the common range of unsigned int and signed
    int is guaranteed to have the same representation.
    I do not find anything in the standard against either
    signed: sign bit -- four padding bits -- 31 value bits
    unsigned: five padding bits -- 31 value bits
    or
    signed: sign bit -- four padding bits -- 31 value bits
    unsigned: four padding bits -- 32 value bits
    or
    signed: sign bit -- four padding bits -- 31 value bits
    unsigned: 36 value bits
    or, what you were hoping for
    signed: sign bit -- four padding bits -- 31 value bits
    unsigned: one value bit -- four padding bits -- 31 value bits
    where the above specifies the "bit order" of the representation.
    So, without the stipulation that unsigned has one more value
    bit than signed int and that that additional value bit is
    "in the same place" as the sign bit of the signed int, your
    expectations may be off.
    You may shift too far for identical numbers of value bits in
    the first of the above cases. Or you may fail to set the "sign
    bit" in the second case.

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Aug 25, 2006
    #5
    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. Peter
    Replies:
    5
    Views:
    14,032
    Dale King
    Jun 2, 2006
  2. Pietro Cerutti

    char * signedness

    Pietro Cerutti, Jul 5, 2007, in forum: C Programming
    Replies:
    17
    Views:
    627
  3. Alef Veld

    bitshifting

    Alef Veld, Apr 28, 2008, in forum: C Programming
    Replies:
    12
    Views:
    460
    Barry Schwarz
    Apr 30, 2008
  4. Angus
    Replies:
    5
    Views:
    340
    James Kanze
    Oct 12, 2009
  5. Philipp Klaus Krause

    int*_t, int_least*_t, int_fast*_t signedness

    Philipp Klaus Krause, Jun 14, 2010, in forum: C Programming
    Replies:
    5
    Views:
    612
    Keith Thompson
    Jun 14, 2010
Loading...

Share This Page