(getting rather offtopic now, so I've tried to keep it short) > From: owner-openssl-...@openssl.org On Behalf Of Ger Hobbelt > Sent: Friday, 12 December, 2008 05:12
> On Fri, Dec 12, 2008 at 1:31 AM, Dave Thompson > <dave.thomp...@princetonpayments.com> wrote: <snip: about getting an aligned buffer> > > Note that this method will give (byte*)rawptr+wordsize in the case > > rawptr is already aligned, which for _malloc it *usually* will be. > > BUG in my code - and a grievious mistake at that. :-( Wasn't my best > day, yesterday. > > [added backedit line above] > > > int shift = wordsize; > > shift -= ((int)rawptr) % wordsize; > --> > unsigned int shift = wordsize - 1; > shift -= ((unsigned int)rawptr) % wordsize; > Sorry, that's worse. That makes (byte*)rawptr +shift _always_ misaligned. > > > Or, we can easily use (byte*)rawptr+0 in that 'special' case: > > al_ptr = ((unsigned)rawptr + wordsize-1) & -wordsize; > > May I? nitpick: casting back to pointer is missing. I like the Yes, that's fair. But at least the compiler catches this one. > -wordsize (I always used ~wordsize, which is what you really want and > identical for 2's complement signed int machines - do we still have > the other kind around, BTW?) > No, those are quite different. Assuming (as before) that wordsize is a power of two, thus only one bit set in binary, wordsize-1 is all the bits below it, and -wordsize is all the bits at and above it. Done in unsigned arithmetic it doesn't matter whether the machine is 2sC or not, although as you imply in practice all are. Oops, I see wordsize wasn't unsigned -- either make it so, or cast it. Obviously its value should never be negative (or zero); that wouldn't make sense. ~wordsize is different, and unuseful here. 2sC -x is ~x PLUS ONE. (That's why some early machines preferred 1sC: you don't have to wait for carry propagation, as you do in 2sC, in the days when carry lookahead meant a whole extra rack of tubes or at least a board of diodes.) > And I did the modulo-plus-pointer-shift thing above instead of this > bit-masking-shoving-into-int-and-back-into-pointer (which is faster on > all machines I know) to allow for those platforms where a pointer does > not fit an int (or a long) (e.g. MSVC2005 64-bit i86: int/long = 32 > bit, long long = 64 bit, but then 'long long' doesn't exist on older > C89 environments, so harder to port (ahem). > To be exact, where ptr doesn't fit any (safely) available UNSIGNED integer type. That's a good point. Then my method needs to be more like: /* assumes common uchar,uint, obvious fixes otherwise */ void* rawptr = malloc_or_whatever; uint good = ((uint)rawptr +wordsize-1) & -/*(uint)*/wordsize ; uchar* al_ptr = (uchar*)rawptr + (good -(uint)rawptr); /* note the second and third terms are done in unsigned arithmetic, hence with wraparound, BEFORE adding the result to rawptr, which is vital when rounding up to next bit above uint's width; may prefer to shift that step to the line above to ensure less-skilled maintainers don't wrongly 'optimize' this. */ The other way that works mathematically (unsigned or 2sC) is: -( -(integer)rawptr & -wordsize ) but IME this confuses many people, and ends up needing a comment bigger than just coding the other method, so I usually don't. Or if ptr doesn't fit in available unsigned integer: uint good = - (-(uint)rawptr & -uwordsize); uchar* al_ptr = (uchar*)rawptr +(good -(uint)rawptr); but now it's confusing AND inelegant. > Thanks for the exchange. Now I can cope with Friday morning again. I hate ALL mornings. You may notice my posts are late in the day (in Eastern US winter = -0500 if that isn't obvious). <G> ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org