Implement C23 memalignment
Paul Eggert
eggert@cs.ucla.edu
Fri Oct 3 07:13:32 GMT 2025
On 2025-10-02 13:43, Zack Weinberg wrote:
> as has
> been pointed out elsethread, the expected usage is `memalignment(p) >= k`,
> where k is a power of two, and this can be compiled efficiently with
> only the basic set of bitwise operations.
It's still not going to be as efficient as the non-memalignment code,
partly because memalignment is squirrelly with the null pointer, and
partly because I doubt whether compiler-writers will bother to look for
entire expressions of that particular form (you can't simply look at
memalignment in isolation).
> (NB I haven't checked whether CheriBSD
> provides `uintptr_t` or what its ABI says is the result of casting a
> pointer to a suitably large integer type.)
I *have* checked, and Cheri is not a problem. CheriBSD has uintptr_t,
and the non-memalignment test for misaligned pointers works fine with it
even though uintptr_t is 128 bits wide. Joseph's proposed implementation
of memalignment also works fine, though of course it's slower than the
non-memalignment code.
Nobody will be so foolish as to break this kind of pointer arithmetic,
as it has been in widespread use since the 1970s and looooots of
programs assume it. (The Gnulib documentation even says it's fine to do
it.) Practically speaking, the only way to shake loose from this
assumption will be to stop using C, and let's not worry about that
possibility when talking about a C feature.
> And I think we *do* want to reiterate here that "an alignment" has to
> be a power of two
Sure, that's fine.
> I expect
> that compilers that *do* advertise C2023 support are going to emit
> optimal code for expressions involving this function in short order.
If they do that (and I am skeptical it would be any time soon), we can
change the documentation then. In the meantime we should document what
we have, not what we hope for sometime in the future.
> The @dfn{alignment} of a pointer is the largest power of two that
> evenly divides the pointer's numeric value.
This is wrong for null pointers. And doesn't define what a pointer's
"numeric value" is.
> or a null pointer. As a GNU extension, @theglibc{} guarantees
> to return the mathematically correct result for any input,
> whether or not it is a valid pointer.
Here it's not clear what "mathematically correct" means.
If we're going to go into this level of detail, it's both simpler and
more specific to say "memalignment (p) is equivalent to ((size_t) p & -
(size_t) p)" (and then give an example) than to fool around saying vague
and possibly-confusing phrases like "numeric value" and "mathematically
correct". Just say exactly what it does in clear language.
> On almost all current CPU architectures,
> when @var{a} is a power of two, these expressions are equivalent:
>
> @example
> memalignment (p) >= a
> p && ((uintptr_t) p & (a - 1)) == 0
> @end example
It's clearer to put it the following way instead, because the code is
testing for a misaligned pointer and a null pointer is not misaligned:
p == NULL || memalignment (p) >= a
((uintptr_t) p & (a - 1)) == 0
... to underscore the fact that memalignment is squirrelly on null
pointers: it returns 0 as a representation of infinity.
> Architectures where the second of these expressions doesn't work might
> become more common in the future,
That's so unlikely that we shouldn't waste the reader's time mentioning
it here.
More information about the Libc-alpha
mailing list