Inconsistent behaviour for (1 << 32)

Discussion in 'C Programming' started by Keith Thompson, Oct 20, 2007.

  1. Daniel Kraft <> writes:
    > I did encounter a strange problem in my C program, and traced it down;
    > it looks like I get different results for bit left shifts when the bit
    > count is a constant or a funtion-return value.
    >
    > When doing (1 << 32) for a 32-bit-unsigned I expect to get 0; can I
    > assume this, or is this something I should never do?

    [...]

    It's something you should never do. Quoting the standard,

    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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 20, 2007
    #1
    1. Advertising

  2. A left or right shift of a value x by n invokes undefined behaviour if
    n is negative, or greater than or equal to the number of bits in x.
    Note that this includes the case "equal". So for 32 bit values, x <<
    32 invokes undefined behaviour.

    Don't do it.
    christian.bau, Oct 20, 2007
    #2
    1. Advertising

  3. Daniel Kraft said:

    > Hi,
    >
    > I did encounter a strange problem in my C program, and traced it down;
    > it looks like I get different results for bit left shifts when the bit
    > count is a constant or a funtion-return value.
    >
    > When doing (1 << 32) for a 32-bit-unsigned I expect to get 0;


    The behaviour is undefined if the number of bits by which you are shifting
    is >= the number of bits in the object.

    3.3.7 of C89 says: "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
    Richard Heathfield, Oct 20, 2007
    #3
  4. Keith Thompson

    Daniel Kraft Guest

    Hi,

    I did encounter a strange problem in my C program, and traced it down;
    it looks like I get different results for bit left shifts when the bit
    count is a constant or a funtion-return value.

    When doing (1 << 32) for a 32-bit-unsigned I expect to get 0; can I
    assume this, or is this something I should never do? However, running
    the attached code gives me two different outputs (1 0) when run, while I
    expected it to print 0 0.

    I use gcc 4.2.1 like this:
    gcc -pedantic -std=c99 test.c -o test

    When I turn on optimization, I get the expected results! Is this some
    compiler problem or does my program trigger some undefined behaviour?

    Thanks,
    Daniel


    #include <stdio.h>
    #include <stdint.h>
    #include <assert.h>

    #define NUM_BITS ((unsigned short)(8*sizeof(unsigned)))

    unsigned short getBits()
    {
    return NUM_BITS;
    }

    int main()
    {
    unsigned a=(1 << getBits());
    unsigned b=(1 << NUM_BITS);
    assert(NUM_BITS==getBits());
    printf("%u %u\n", a, b);
    return 0;
    }
    Daniel Kraft, Oct 20, 2007
    #4
  5. "Daniel Kraft" <> a écrit dans le message de news:
    ffchgo$4gh$...
    > >> I did encounter a strange problem in my C program, and traced it down;
    > >> it looks like I get different results for bit left shifts when the bit
    > >> count is a constant or a funtion-return value.
    > >>
    > >> When doing (1 << 32) for a 32-bit-unsigned I expect to get 0;

    > >
    > > The behaviour is undefined if the number of bits by which you are

    > shifting is >= the number of bits in the object.
    >
    > Ok, thank you!
    >
    > What I'm trying to do is this: I've got some unsigned type, and a
    > function which returns a number of bits <= the number of usable bits of
    > this type.
    >
    > I need to calculate (1 << getBits())-1, i.e., set the lower getBits() bits
    > to one (which might be all ones if it is equal to the type's width, but it
    > also might be only some less-significant-bits ones).
    >
    > Is there some other clever way to do this?


    Use an array of unsigned ints with 33 elements.

    unsigned int mask = mask_array[getBits()];

    Or use a test:

    unsigned n = getBits();
    unsigned mask = (n < sizeof(unsigned) * CHAR_BIT) ? (1U << n) - 1 : -1U;

    Ultimately, if you know that getBits() > 0 and no greater than the width of
    the unsigned type, use this expression:

    unsigned mask = ((1U << (getBits() - 1)) << 1) - 1;

    or even:

    unsigned mask = ~(-2U << (getBits() - 1));

    or optimally:

    unsigned mask = -1U >> (sizeof(unsigned) * CHAR_BIT - getBits());

    --
    Chqrlie.
    Charlie Gordon, Oct 20, 2007
    #5
  6. "Daniel Kraft" <> a écrit dans le message de news:
    ffcjh5$8s6$...
    > Daniel Kraft wrote:
    >> >> I did encounter a strange problem in my C program, and traced it

    >> down;
    >> >> it looks like I get different results for bit left shifts when the

    >> bit
    >> >> count is a constant or a funtion-return value.
    >> >>
    >> >> When doing (1 << 32) for a 32-bit-unsigned I expect to get 0;
    >> >
    >> > The behaviour is undefined if the number of bits by which you are

    >> shifting is >= the number of bits in the object.
    >>
    >> Ok, thank you!
    >>
    >> What I'm trying to do is this: I've got some unsigned type, and a
    >> function which returns a number of bits <= the number of usable bits of
    >> this type.
    >>
    >> I need to calculate (1 << getBits())-1, i.e., set the lower getBits()
    >> bits to one (which might be all ones if it is equal to the type's width,
    >> but it also might be only some less-significant-bits ones).

    >
    > I think I found a solution:
    >
    > instead of (1 << getBits()) which might result in this undefined behaviour
    > I do (2 << (getBits()-1)) (getBits() is never 0). This should be
    > well-defined, right?


    So you came up with one of my proposed solutions on your own ;-)

    This one is well defined only upto 31, because 2 is an int, and behaviour on
    overflow is implementation defined. Use (2U << (getBits()-1)) to fix this,
    but look at my last proposal elsethread that requires fewer operations to
    compute the mask itself.

    --
    Chqrlie.
    Charlie Gordon, Oct 20, 2007
    #6
  7. Keith Thompson

    Martin Wells Guest

    Daniel:

    > instead of (1 << getBits()) which might result in this undefined
    > behaviour I do (2 << (getBits()-1)) (getBits() is never 0). This should
    > be well-defined, right?



    Sounds good. Still don't know why you're shifting signed integer types
    though.

    Martin
    Martin Wells, Oct 20, 2007
    #7
  8. Keith Thompson

    Daniel Kraft Guest

    >> I did encounter a strange problem in my C program, and traced it down;
    >> it looks like I get different results for bit left shifts when the bit
    >> count is a constant or a funtion-return value.
    >>
    >> When doing (1 << 32) for a 32-bit-unsigned I expect to get 0;

    >
    > The behaviour is undefined if the number of bits by which you are

    shifting is >= the number of bits in the object.

    Ok, thank you!

    What I'm trying to do is this: I've got some unsigned type, and a
    function which returns a number of bits <= the number of usable bits of
    this type.

    I need to calculate (1 << getBits())-1, i.e., set the lower getBits()
    bits to one (which might be all ones if it is equal to the type's width,
    but it also might be only some less-significant-bits ones).

    Is there some other clever way to do this?

    Thanks,
    Daniel

    --
    Got two Dear-Daniel-Instant Messages
    by MSN, associate ICQ with stress--so
    please use good, old E-MAIL!
    Daniel Kraft, Oct 20, 2007
    #8
  9. Keith Thompson

    Daniel Kraft Guest

    Daniel Kraft wrote:
    > >> I did encounter a strange problem in my C program, and traced it down;
    > >> it looks like I get different results for bit left shifts when the bit
    > >> count is a constant or a funtion-return value.
    > >>
    > >> When doing (1 << 32) for a 32-bit-unsigned I expect to get 0;

    > >
    > > The behaviour is undefined if the number of bits by which you are

    > shifting is >= the number of bits in the object.
    >
    > Ok, thank you!
    >
    > What I'm trying to do is this: I've got some unsigned type, and a
    > function which returns a number of bits <= the number of usable bits of
    > this type.
    >
    > I need to calculate (1 << getBits())-1, i.e., set the lower getBits()
    > bits to one (which might be all ones if it is equal to the type's width,
    > but it also might be only some less-significant-bits ones).


    I think I found a solution:

    instead of (1 << getBits()) which might result in this undefined
    behaviour I do (2 << (getBits()-1)) (getBits() is never 0). This should
    be well-defined, right?

    Cheers,
    Daniel


    --
    Got two Dear-Daniel-Instant Messages
    by MSN, associate ICQ with stress--so
    please use good, old E-MAIL!
    Daniel Kraft, Oct 20, 2007
    #9
    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. Razvan

    Inconsistent behaviour

    Razvan, Oct 3, 2004, in forum: Java
    Replies:
    19
    Views:
    551
    Carl Howells
    Oct 11, 2004
  2. Ian Davies

    CSS inconsistent behaviour

    Ian Davies, May 14, 2006, in forum: HTML
    Replies:
    6
    Views:
    429
    Neredbojias
    May 18, 2006
  3. =?iso-8859-15?Q?Peter_Kn=F6rrich?=

    Inconsistent float behaviour on "inf" - current state?

    =?iso-8859-15?Q?Peter_Kn=F6rrich?=, Jun 27, 2006, in forum: Python
    Replies:
    1
    Views:
    442
    Scott David Daniels
    Jun 27, 2006
  4. Serengeti
    Replies:
    2
    Views:
    476
    Serengeti
    Nov 20, 2005
  5. MB

    Inconsistent webservice behaviour

    MB, Dec 8, 2004, in forum: ASP .Net Web Services
    Replies:
    0
    Views:
    128
Loading...

Share This Page