shift, signed unsigned

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Schüle Daniel

    #1

    shift, signed unsigned

    Hello Newsgroup,

    I was thinking about integer literals and what default types they get
    and how they behave when applied to shift operator

    assume sizeof(int) == sizeof(unsigend int) = 4


    int ii = -1024;
    cout << (ii>>1) << endl; // -512
    cout << (ii>>2) << endl; // -256

    so the sign remains, meaning the most left bit is
    not shifted, is this standard behaviour or impl. defined?



    cout << (-4>>1) << endl; // -2
    cout << (-4>>2) << endl; // -1
    cout << (-4>>3) << endl; // -1

    as one can see -1>>1 doesn't drop to 0
    (I would expect it)
    is this standard behaviuor?



    cout << (1<<30) << endl;
    1 has type int, 1 << 30 is int too, so this is ok

    cout << (1<<31) << endl;
    1 has type int, 1 << 31 would set the sign bit
    if the expression remains "int" it would be negative
    if on the other hand, it would be converted to
    "unsigned int" it would be positive
    I do get -2147483648 so my compiler chooses it to
    remain "int". Again is this standard or impl. defined?

    cout << (1U<<31) << endl;
    1U has type "unsigned int", so is 1U<<31 too
    I get here 2147483648
    I think this is always ok.


    and the last question

    cout << typeid(0x800000 0).name() << endl; // i *
    cout << typeid(0x800000 00).name() << endl; // j **

    gcc (GCC) 4.0.2
    i means int, j means unsigned int
    I always thought that literals like 1 or 100
    are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
    but what I see here is that compiler puts ** in "unsigned int".
    (If it wouldn't do it, we would get negative number.)
    Why chooses compiler unsigned int? it this standard behaviour or impl.
    defined?

    Regards, Daniel


  • Old Wolf

    #2
    Re: shift, signed unsigned

    Schüle Daniel wrote:
    [color=blue]
    > Hello Newsgroup,
    >
    > I was thinking about integer literals and what default types they get
    > and how they behave when applied to shift operator[/color]

    Buy the C++ standard, it answers all of your questions :)
    [color=blue]
    > assume sizeof(int) == sizeof(unsigend int) = 4
    >
    > int ii = -1024;
    > cout << (ii>>1) << endl; // -512
    > cout << (ii>>2) << endl; // -256
    > cout << (-4>>1) << endl; // -2
    > cout << (-4>>2) << endl; // -1
    > cout << (-4>>3) << endl; // -1
    >
    > as one can see -1>>1 doesn't drop to 0
    > (I would expect it)
    > is this standard behaviuor?[/color]

    Right-shifting a negative number is implementation-defined.
    (Obviously what's happening is that 111........111 being
    right-shifted is still 111.........111 ).
    [color=blue]
    > cout << (1<<31) << endl;
    > 1 has type int, 1 << 31 would set the sign bit
    > if the expression remains "int" it would be negative
    > if on the other hand, it would be converted to
    > "unsigned int" it would be positive
    > I do get -2147483648 so my compiler chooses it to
    > remain "int". Again is this standard or impl. defined?[/color]

    1 << 31 has the value of 2 to the power 31. This value
    can't be represented by an int, so the behaviour is
    undefined. (This is the same as any other integer overflow).
    [color=blue]
    > cout << (1U<<31) << endl;
    > 1U has type "unsigned int", so is 1U<<31 too
    > I get here 2147483648
    > I think this is always ok.[/color]

    2^31 can fit in an unsigned integer, so there's no problem here.
    [color=blue]
    > cout << typeid(0x800000 0).name() << endl; // i *
    > cout << typeid(0x800000 00).name() << endl; // j **
    >
    > gcc (GCC) 4.0.2
    > i means int, j means unsigned int
    > I always thought that literals like 1 or 100
    > are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
    > but what I see here is that compiler puts ** in "unsigned int".[/color]

    2.13.1#2 says:

    If it is octal or hexadecimal and has no suffix, it has the
    first of these types in which its value can be represented:
    int, unsigned int, long int, unsigned long int.

    0x8000000 (2^27) fits in an int, so it is an int.
    0x80000000 (2^31) does not fit in an int but does fit in an
    unsigned int, so it is an unsigned int.
    [color=blue]
    > (If it wouldn't do it, we would get negative number.)[/color]

    2^31 is a large positive number. It is never negative. Many
    people get this wrong. You might get a negative number as
    the result of implementation-defined behaviour when you try
    and assign this large positive number, to a signed int that
    cannot hold such a large number.

    Comment

    • Victor Bazarov

      #3
      Re: shift, signed unsigned

      Schüle Daniel wrote:[color=blue]
      > I was thinking about integer literals and what default types they get
      > and how they behave when applied to shift operator
      >
      > assume sizeof(int) == sizeof(unsigend int) = 4
      >
      >
      > int ii = -1024;
      > cout << (ii>>1) << endl; // -512
      > cout << (ii>>2) << endl; // -256
      >
      > so the sign remains, meaning the most left bit is
      > not shifted, is this standard behaviour or impl. defined?[/color]

      Implementation-defined.
      [color=blue]
      > cout << (-4>>1) << endl; // -2
      > cout << (-4>>2) << endl; // -1
      > cout << (-4>>3) << endl; // -1
      >
      > as one can see -1>>1 doesn't drop to 0
      > (I would expect it)
      > is this standard behaviuor?[/color]

      Implementation-defined.
      [color=blue]
      > cout << (1<<30) << endl;
      > 1 has type int, 1 << 30 is int too, so this is ok[/color]

      Yes.
      [color=blue]
      > cout << (1<<31) << endl;
      > 1 has type int, 1 << 31 would set the sign bit
      > if the expression remains "int" it would be negative
      > if on the other hand, it would be converted to
      > "unsigned int" it would be positive
      > I do get -2147483648 so my compiler chooses it to
      > remain "int". Again is this standard or impl. defined?[/color]

      Kind of. The result of (1<<31) is the same as

      (1 * 2^31) % (UINT_MAX+1)

      Since the destination type is signed, and the value can be
      represented, it is represented using the same bit pattern,
      otherwise it's implementation-defined.
      [color=blue]
      > cout << (1U<<31) << endl;
      > 1U has type "unsigned int", so is 1U<<31 too
      > I get here 2147483648
      > I think this is always ok.[/color]

      Yes.
      [color=blue]
      > and the last question
      >
      > cout << typeid(0x800000 0).name() << endl; // i *
      > cout << typeid(0x800000 00).name() << endl; // j **
      >
      > gcc (GCC) 4.0.2
      > i means int, j means unsigned int
      > I always thought that literals like 1 or 100
      > are always "int" unless explicitelly marked as 1U or 1UL or 1ULL
      > but what I see here is that compiler puts ** in "unsigned int".[/color]

      Yes. According to the Standard.
      [color=blue]
      > (If it wouldn't do it, we would get negative number.)
      > Why chooses compiler unsigned int? it this standard behaviour or impl.
      > defined?[/color]

      Not really. The sequence it tries is 'int', then 'unsigned', then 'long',
      then 'unsigned long'. If there is no suffix, that is.

      V
      --
      Please remove capital As from my address when replying by mail


      Comment

      • dc

        #4
        Re: shift, signed unsigned

        Here is a simple rule:

        Right shift of unsigned number : inserts bit 0 from MSB/Left
        Right shift of signed number : inserts bit 1 from MSB/Left

        Left shift behaves same for both signed and unsigned number:
        inserts bit 0 from LSB/Right

        Comment

        • m_schellens@hotmail.com

          #5
          Re: shift, signed unsigned

          dc wrote:[color=blue]
          > Here is a simple rule:
          >
          > Right shift of unsigned number : inserts bit 0 from MSB/Left
          > Right shift of signed number : inserts bit 1 from MSB/Left[/color]

          Probably that rule is a bit too simple:
          What about postive signed numbers and signed zero?

          Cheers,
          Marc

          [color=blue]
          > Left shift behaves same for both signed and unsigned number:
          > inserts bit 0 from LSB/Right[/color]

          Comment

          • dc

            #6
            Re: shift, signed unsigned

            Ok .. Read signed number as negative numbers
            Unsigned number as positive numbers...


            Thanks 4 catching...

            Comment

            Working...