Date: Thu, 6 Jul 2023 10:42:10 -0400
On Thu, Jul 6, 2023 at 2:36AM Lénárd Szolnoki via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> Hi,
>
> [...]
>
> The standard does talk about alignment of single pointers, but I don't think it defines it properly. std::align and std::assume_aligned also comes to mind in addition to allocation functions.
>
> I also think that this is a hole in the standard. I think it's possible to define it in an abstract manner without exposing the underlying integer nature of pointers/addresses in most implementations.
I don't see how these properties aren't implied by the current rules.
Going through them:
> Something along these lines:
> * "aligned" is a relationship between an address and a number that is a power of two
[basic.align]/1 implies that an object either can or cannot be
allocated at a given address, depending on whether the address is
restricted by its type's alignment requirement. [basic.align]/5
clarifies this in terms of "satisfying an alignment requirement" as a
binary relation between addresses and alignment requirements; every
address either satisfies an alignment requirement (and an object with
that requirement can be allocated at that address), or it fails to
satisfy an alignment requirement (and such an object cannot be
allocated). [basic.align]/4 requires every alignment value to be a
power of two.
> * pointer values represent addresses
This is in [basic.compound]/3.
> * if an address is aligned 2^N, then it's aligned 2^M for every 0<=M<=N.
This is implied by [basic.align]/4 (values are powers of two),
[basic.align]/5 (satisfying a stronger alignment implys satisfying a
weaker alignment), and /(7.3) (stronger alignments have greater values
than weaker alignments).
> * every address is aligned 1
This is implied by [basic.align]/1: every byte of memory has a unique
address, so each successive address is 1 byte apart; thus, an object
type with an alignment requirement of 1 can by allocated at any
address, or equivalently, every address satisfies an alignment
requirement of 1.
> * details how pointer arithmetic preserves alignment (underlying idea: if an address is aligned 2^N then moving the address by multiples of 2^N bytes, then the resulting address is also aligned 2^N)
This preservation property is stated in [basic.align]/1. Though the
current wording might support a really weird reading, where some block
of storage might not have any addresses that satisfy a certain
alignment requirement, even if it is large enough. (After all, if
there are no aligned addresses at which an object can be allocated,
then we can vacuously say anything about the differences between those
addresses!) That is to say, I don't see what implies the general
property that "a block of storage with 2^N bytes must contain at least
one address (including the one-past-the-end address) that satisfies an
alignment requirement of 2^N".
> * the address of objects with alignment requirement x has to be aligned x.
This is in [basic.align]/1.
> Cheers,
> Lénárd
Where exactly is this hole that you are seeing?
<std-discussion_at_[hidden]> wrote:
> Hi,
>
> [...]
>
> The standard does talk about alignment of single pointers, but I don't think it defines it properly. std::align and std::assume_aligned also comes to mind in addition to allocation functions.
>
> I also think that this is a hole in the standard. I think it's possible to define it in an abstract manner without exposing the underlying integer nature of pointers/addresses in most implementations.
I don't see how these properties aren't implied by the current rules.
Going through them:
> Something along these lines:
> * "aligned" is a relationship between an address and a number that is a power of two
[basic.align]/1 implies that an object either can or cannot be
allocated at a given address, depending on whether the address is
restricted by its type's alignment requirement. [basic.align]/5
clarifies this in terms of "satisfying an alignment requirement" as a
binary relation between addresses and alignment requirements; every
address either satisfies an alignment requirement (and an object with
that requirement can be allocated at that address), or it fails to
satisfy an alignment requirement (and such an object cannot be
allocated). [basic.align]/4 requires every alignment value to be a
power of two.
> * pointer values represent addresses
This is in [basic.compound]/3.
> * if an address is aligned 2^N, then it's aligned 2^M for every 0<=M<=N.
This is implied by [basic.align]/4 (values are powers of two),
[basic.align]/5 (satisfying a stronger alignment implys satisfying a
weaker alignment), and /(7.3) (stronger alignments have greater values
than weaker alignments).
> * every address is aligned 1
This is implied by [basic.align]/1: every byte of memory has a unique
address, so each successive address is 1 byte apart; thus, an object
type with an alignment requirement of 1 can by allocated at any
address, or equivalently, every address satisfies an alignment
requirement of 1.
> * details how pointer arithmetic preserves alignment (underlying idea: if an address is aligned 2^N then moving the address by multiples of 2^N bytes, then the resulting address is also aligned 2^N)
This preservation property is stated in [basic.align]/1. Though the
current wording might support a really weird reading, where some block
of storage might not have any addresses that satisfy a certain
alignment requirement, even if it is large enough. (After all, if
there are no aligned addresses at which an object can be allocated,
then we can vacuously say anything about the differences between those
addresses!) That is to say, I don't see what implies the general
property that "a block of storage with 2^N bytes must contain at least
one address (including the one-past-the-end address) that satisfies an
alignment requirement of 2^N".
> * the address of objects with alignment requirement x has to be aligned x.
This is in [basic.align]/1.
> Cheers,
> Lénárd
Where exactly is this hole that you are seeing?
Received on 2023-07-06 14:42:22