This is a discussion on Re: shifting curiosity within the mailing.openbsd.tech forums, part of the OpenBSD category; --> On Thu, Jun 16, 2005 at 06:29:42PM +0200, Moritz Grimm wrote: > Hi, > > today, I came across ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| On Thu, Jun 16, 2005 at 06:29:42PM +0200, Moritz Grimm wrote: > Hi, > > today, I came across an idiosyncrasy wrt shifting in C/C++, at least > with gcc and g++ on OpenBSD/i386. > > The following snippet demonstrates it in a form that also occurs quite a > few times similarily in OpenBSD source code, e.g. in > src/usr.sbin/bgpctl/parser.c and various other places (each with more or > less likelihood of ``bits'' ever being 0): > > { > unsigned int mask1, mask2; > int bits; > > bits = 0; > > mask1 = 0xffffffff << (32 - bits); > mask2 = (unsigned long long)0xffffffff << (32 - bits); > > [...] > } > > mask1 and mask2 are not the same. The value of mask1 is 0xffffffff, as > if it were left-shifted by 0, while mask2 is 0. Concerning prefix > lengths of CIDR network numbers, the latter is clearly what we want, so > that 0.0.0.0/0 doesn't break (I need this in a different context, which > made me stumble over this in every case, not only when dealing with an > actual 0.0.0.0/0 network.) > > The reason for this seems that even without optimization, the amount of > bits to shift is mod'ed with the amount of bits in the type the shifting > is done with - 32 % 32 = 0, ergo no shifting is being done. > > My solution is to cast the unshifted mask to 64bit and let the > casting-back-to-32bit take care of making the 1s disappear for good. > > What I am curious about is whether all of this is intended behavior, and > why (I find it strange) - other than that, please consider this as a > general FYI, as this *might* be a problem in some places in OpenBSD > (userland mostly, I suppose). > > > Moritz This is as specified in C. From Kernighan & Ritchie, second edition (The ANSI C book). In section A7.8 "Shift Operators" it says: "The result is undefined if the right operand is negative, or greater than or equal to the number of bits in the left expression's type." Thus shifting a 32 bit unsigned int up by 32 bits is officially undefined. Yes - I was bitten by this some years ago. Cheers -- Dave Hines. |