Given alignas(N) char buffer[N];
and a char* p
between [&buffer[0]
, &buffer[N-1]
], can I obtain a pointer to buffer[0]
by using p
and N
?
char* previous_aligned_pointer(char* ptr, size_t align) {
// how?
}
int main() {
constexpr int N = 32;
alignas(N) char buffer[N];
assert(previous_aligned_pointer(&buffer[rand() % N], N) == &buffer[0]);
}
I'd like to do it in portable C++ (if possible), so something like casting a pointer to uintptr_t
and then performing arithmetic on it may not be used.
Aligned Pointer means that pointer with adjacent memory location that can be accessed by a adding a constant and its multiples. for char a[5] = "12345"; here a is constant pointer if you and the size of char to it every time you can access the next chracter that is, a +sizeofchar will access 2.
new and malloc, by default, align address to 8 bytes (x86) or 16 bytes (x64), which is the optimal for most complex data.
Hands down the fastest way to align a pointer is to use 2's complement math. You need to invert the bits, add one, and mask off the 2 (for 32-bit) or 3 (for 64-bit) least significant bits.
The alignas type specifier is a portable, C++ standard way to specify custom alignment of variables and user defined types. The alignof operator is likewise a standard, portable way to obtain the alignment of a specified type or variable. You can use alignas on a class, struct or union, or on individual members.
The C++ standard doesn't specify packing behavior for alignment on boundaries smaller than the compiler default for the target platform, so you still need to use the Microsoft #pragma pack in that case. Use the aligned_storage class for memory allocation of data structures with custom alignments.
For 16-bit alignment just mask the pointer with 0x1 and add that value. Algorithm works identically in any language but as you can see, Embedded C++ is vastly superior than C in every way shape and form.
There is a standard library function to get the next aligned pointer. It's called std::align
. You could then subtract the alignment to get the previous one.
In general that may do pointer arithmetic beyond the buffer in which case the subtraction would technically be UB. If that's a concern, then you could avoid the UB if you can allocate extra space in the buffer such that the next aligned pointer is always within the buffer.
Only other way is to implement it yourself which would have to rely on conversion to integer type which relies on implementation dependent unguaranteed behaviour. In conclusion: No, I don't think there's a general strictly standard conforming solution.
However, for your example case, there's no problem. The next aligned address is pointer past the end, so it's fine to subtract N to get the address to beginning of the buffer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With