This is a discussion on shifting curiosity within the mailing.openbsd.tech forums, part of the OpenBSD category; --> Hi, today, I came across an idiosyncrasy wrt shifting in C/C++, at least with gcc and g++ on OpenBSD/i386. ...
| |||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| 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 |