> From: owner-openssl-...@openssl.org On Behalf Of Ger Hobbelt
> Sent: Sunday, 14 December, 2008 14:18
<snip some>
> What I was trying to attain was a 'correction offset', derived from
> the originally unaligned pointer, and add that to the pointer (while
> having it cast as a byte* pointer so offsets would be counted as
> bytes).
> 
> In your code the offset is (good - (uint)rawptr).
> 
If pointers don't (or might not) fit in (u)integers, yes.
If they do fit in e.g. ulong, I just use that directly.

> I used a (slower) modulo operator, so the signed/unsigned type of the
> final offset result isn't important as only the lowest bits will end
> up in there due to unsigned intermediates. For power-of-2 wordsize the
> modulo wordsize === bitwise-and (wordsize-1)
> 
The intermediate is only unsigned if you make it so. C defines % for
both signed and unsigned, but signed is likely (C89) or certain (C99) 
to give the wrong result for values in (cast to) the negative 'half'
of signed as you first had. (Pascal, if I remember, defines MOD and REM 
differently for negative, and you can get what you need here. Not C.)

Modulo power-of-2 (of unsigned or nonnegative) is bitand, yes. 
In fact if a compiler sees that, it will usually do the optimization 
for you. But this function has wordsize passed as an argument so 
the compiler can't see it, unless you get it to be inlined -- 
which at minimum means copied/#include'd into each client module.
(For some compilers you also need C99 'inline', or a pragma, or such.)

Another way is to make the argument be log2_wordsize i.e. the number 
of bits of alignment, then do %(1U<<nbit) ; that is arguably clearer.
Alternatively a code macro is always inlined, and defensible for a 
simple thing like this (1 maybe 2 codelines really needed).

> void* rawptr = malloc_or_whatever;
> if (wordsize <= 0) goto err;
> /*
> uint offset = (((uint)wordsize) - ((uint)rawptr)) % wordsize;
>    or for power-of-2 wordsizes only:
> */
> uint offset = (((uint)wordsize) - ((uint)rawptr)) & (wordsize - 1);
> uchar* al_ptr = ((uchar*)rawptr) + offset;
> 
For non-power-of-2 that % version wouldn't work right either. 
If you ALSO keep the one you had before:
  offset = ( wordsize - (utype)rawptr % wordsize ) % wordsize
it will, IF utype is big enough to hold pointer values.
If there isn't a big enough u-integer, you can't just take the low bits
as you can for power-of-2, you have to do 'multiprecision' integer
or more complicated tricks to correct for the residues.
Real machines ARE power-of-2 so I don't think it's worth it.



______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to