473,386 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Inconsistent behaviour for (1 << 32)

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;
}
Oct 20 '07 #1
8 1395
Daniel Kraft <d@domob.euwrites:
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) ks***@mib.org <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"
Oct 20 '07 #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.

Oct 20 '07 #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
Oct 20 '07 #4
>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!
Oct 20 '07 #5
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!
Oct 20 '07 #6
"Daniel Kraft" <d@domob.eua écrit dans le message de news:
ff**********@newsreader2.utanet.at...
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.
Oct 20 '07 #7
"Daniel Kraft" <d@domob.eua écrit dans le message de news:
ff**********@newsreader2.utanet.at...
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.
Oct 20 '07 #8
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

Oct 20 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

129
by: Torbjørn Pettersen | last post by:
I've started cleaning up my HTML and implementing CSS. So far I've used FrontPage, but am switching over to DreamWeaver. Reading a bit on W3Schools.com and W3.org I see there are a lot of HTML...
15
by: kernel.lover | last post by:
Hello, i want to know to have multiple clients connects to same server program does following is correct code #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include...
18
by: mrby | last post by:
All, Here is one question that I can not understand. int main() { int i = 32; printf("%p %p\n", 1<<i, 1<<32); }
9
by: Eric Lindsay | last post by:
I can't figure how to best display little snippets of shell script using <pre>. I just got around to organising to bulk validate some of my web pages, and one of the problems occurs with Bash...
12
by: Filipe Sousa | last post by:
Hi! Could someone explain to me why this operation is not what I was expecting? int main() { int x = 2; std::cout << x << " " << x++ << std::endl; return 0; }
16
by: Mr. Ken | last post by:
Left shift by negative numbers, will I get 1/2? Thanks.
17
by: Dudely | last post by:
My web page displays just fine under IE7, but under IE6 about 90% of it is just plain missing. I get the top of the page, and the bottom of the page... but not the middle. I have not tested with...
4
by: mark4asp | last post by:
I have an element, report which contains tags which have been transformed. E.g. <pis &lt;p&gt <myXml> <report>This text has html tags in it.&lt;p&gt which but <has been changed to &lt;&gt</report>...
1
by: rnhuch | last post by:
My platform is SQL Server 2005. One of the tables of my db has 28589928 rows and one of the fields is real. When I backup and restore this database to another server (using the SQL Server internal...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.