Inconsistent behaviour for (1 << 32)

K

Keith Thompson

Daniel Kraft said:
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.
 
C

christian.bau

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

Richard Heathfield

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."
 
D

Daniel Kraft

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;
}
 
C

Charlie Gordon

Daniel Kraft said:
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());
 
C

Charlie Gordon

Daniel Kraft said:
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.
 
M

Martin Wells

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
 
D

Daniel Kraft

I did encounter a strange problem in my C program, and traced it down;
>
> 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
 
D

Daniel Kraft

Daniel said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top