left shift operator behaves like left rotate when the operand is a variable.

Discussion in 'C Programming' started by pc, Jun 8, 2011.

  1. pc

    pc Guest

    Below is a snippet of code and the result (compiler version also
    mentioned). I fail to understand why the left shift operator behaves
    as if it were the left rotate operator when the operand is a variable.

    $ cat test.c
    #include <stdio.h>
    int main(void)
    {
    unsigned int a = 32, b = 33;
    printf("with constants 1 << 32 = %u, 1 << 33 = %u\n", 1<<32,
    1<<33);
    printf("with variables 1 << 32 = %u, 1 << 33 = %u\n", 1<<a, 1<<b);
    return 0;
    }
    $ gcc test.c
    test.c: In function 'main':
    test.c:6:5: warning: left shift count >= width of type
    test.c:6:5: warning: left shift count >= width of type
    $ ./a.out
    with constants 1 << 32 = 0, 1 << 33 = 0
    with variables 1 << 32 = 1, 1 << 33 = 2
    $ gcc --version
    gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
    pc, Jun 8, 2011
    #1
    1. Advertising

  2. pc <> writes:
    > Below is a snippet of code and the result (compiler version also
    > mentioned). I fail to understand why the left shift operator behaves
    > as if it were the left rotate operator when the operand is a variable.
    >
    > $ cat test.c
    > #include <stdio.h>
    > int main(void)
    > {
    > unsigned int a = 32, b = 33;
    > printf("with constants 1 << 32 = %u, 1 << 33 = %u\n", 1<<32,
    > 1<<33);
    > printf("with variables 1 << 32 = %u, 1 << 33 = %u\n", 1<<a, 1<<b);
    > return 0;
    > }

    [snip]

    I'm guessing unsigned int is 32 bits in your implementation; it would
    have been helpful to tell us that.

    C99 6.5.7p3:

    The integer promotions are performed on each of the operands. The
    type of the result is that of the promoted left operand. If the
    value of the right operand is negative or is greater than or
    equal to the width of the promoted left operand, the behavior
    is undefined.

    So if you shift a 32-bit number by 32 bits, the implementation isn't
    required to behave consistently.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 8, 2011
    #2
    1. Advertising

  3. pc

    crisgoogle Guest

    Re: left shift operator behaves like left rotate when the operand isa variable.

    On Jun 8, 11:05 am, pc <> wrote:
    > Below is a snippet of code and the result (compiler version also
    > mentioned). I fail to understand why the left shift operator behaves
    > as if it were the left rotate operator when the operand is a variable.
    >
    > $ cat test.c
    > #include <stdio.h>
    > int main(void)
    > {
    >     unsigned int a = 32, b = 33;
    >     printf("with constants 1 << 32 = %u, 1 << 33 = %u\n", 1<<32,
    > 1<<33);
    >     printf("with variables 1 << 32 = %u, 1 << 33 = %u\n", 1<<a, 1<<b);
    >     return 0;}
    >
    > $ gcc test.c
    > test.c: In function 'main':
    > test.c:6:5: warning: left shift count >= width of type
    > test.c:6:5: warning: left shift count >= width of type
    > $ ./a.out
    > with constants 1 << 32 = 0, 1 << 33 = 0
    > with variables 1 << 32 = 1, 1 << 33 = 2
    > $ gcc --version
    > gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2


    Read the warning that was given to you!!

    Shifting by greater-than-or-equal-to the width of the shifted type
    is undefined behaviour, so your program could have printed anything.

    What's actually happening to cause your specific output is probably
    this:

    When you use constants, the compiler is "smart" enough to realize
    that you're shifting the bits right off the end, and so the result
    is known at compile time to be zero. When the shift is variable
    however,
    the compiler emits actual shift instructions. A common low-level
    implementation of a shift, down at the CPU level, actually masks out
    anything beyond the 5 bits required to give you a 31-bit shift.
    So if the shift value is 32, you actually get a shift of zero;
    if it's 33, you get a shift of 1.

    Again however, the code you wrote has undefined behaviour, so anything
    can happen. In particular, in this case the output will almost
    certainly be very dependent upon optimization levels, and perhaps
    other "meaningless" changes such as whether a or b are declared
    const (that last bit is just a wild guess, but entirely possible).
    crisgoogle, Jun 8, 2011
    #3
    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. Wenjie
    Replies:
    3
    Views:
    1,012
    Ron Samuel Klatchko
    Jul 11, 2003
  2. Santosh Nayak

    Left Shift / Right Shift Operators

    Santosh Nayak, Nov 30, 2006, in forum: C Programming
    Replies:
    16
    Views:
    1,425
    CBFalconer
    Nov 30, 2006
  3. Marteno Rodia
    Replies:
    1
    Views:
    2,156
    Mike Treseler
    Jun 12, 2007
  4. Prasoon Saurav
    Replies:
    1
    Views:
    494
  5. Sanny
    Replies:
    38
    Views:
    3,327
    Thomas Richter
    Apr 29, 2011
Loading...

Share This Page