PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.c > Inconsistent behaviour for (1 << 32)
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Inconsistent behaviour for (1 << 32)

Réponse
 
LinkBack Outils de la discussion
Vieux 20/10/2007, 09h41   #1
Keith Thompson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

Daniel Kraft <d@domob.eu> 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) kst-u@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"
  Réponse avec citation
Vieux 20/10/2007, 09h43   #2
christian.bau
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

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éponse avec citation
Vieux 20/10/2007, 09h45   #3
Richard Heathfield
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

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
  Réponse avec citation
Vieux 20/10/2007, 10h41   #4
Daniel Kraft
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut 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;
}
  Réponse avec citation
Vieux 20/10/2007, 11h02   #5
Charlie Gordon
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

"Daniel Kraft" <d@domob.eu> a écrit dans le message de news:
ffchgo$4gh$1@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.


  Réponse avec citation
Vieux 20/10/2007, 11h06   #6
Charlie Gordon
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

"Daniel Kraft" <d@domob.eu> a écrit dans le message de news:
ffcjh5$8s6$1@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.


  Réponse avec citation
Vieux 20/10/2007, 12h23   #7
Martin Wells
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

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

  Réponse avec citation
Vieux 20/10/2007, 12h25   #8
Daniel Kraft
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Inconsistent behaviour for (1 << 32)

>> 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!
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 11h29.


Édité par : vBulletin® version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,16715 seconds with 16 queries