Hi everyone, I had a little question about data alignment with a given address.
Assumed we have a address p and we don't know it is 32 bytes aligned or not.
How can we check if it is 32 bytes aligned, if yes, then return original p, if not the return the next address, which is behind p and 32 bytes aligned?
1 2
uint8_t* p; // which is given and has a address p
check_or_find_next_32B_alignment(p);
In general, to round val up to the nearest multiple of X, you do (val+X-1) / X * X.
When X is a power of 2 you can simplify with (val+X-1) & ~X.
The bit manipulation requires an integer type. You can use intptr_t, which is guaranteed to be able to hold a pointer. Here's an example, using all the bad casting operations. :)
#include <iostream>
#include <memory>
#include <cstdint>
int main()
{
const std::size_t SZ = 256*9 ;
char buffer[SZ] {} ;
void* ptr = buffer + 3 ; // +3 to make it an odd address
// bytes available in the buffer from p onwards
std::size_t bytes_available = std::end(buffer) - static_cast<char*>(ptr) ;\
// object we want to place in the buffer is an array of size 253 bytes
// (note: using an odd size of 253 for exposition)
const std::size_t object_size = sizeof( std::uint8_t[253] ) ;
for( int i = 0 ; i < 10 ; ++i )
{
// if we could get a pointer aligned to a 32 byte boundary
if( std::align( 32, object_size, ptr, bytes_available ) )
{
[[maybe_unused]] std::uint8_t* pui8 = static_cast<std::uint8_t*>(ptr) ;
// bytes available in the buffer after this object is placed
bytes_available = std::end(buffer) - static_cast<char*>(ptr) - object_size ;
std::cout << "address: " << ptr << " array of size: " << object_size
<< " bytes left: " << bytes_available << '\n' ;
// bump the pointer to the next available address (to point to the byte immediately after this object)
ptr = static_cast<char*>(ptr) + object_size ;
}
else // std::align failed
{
std::cout << "no more space. buffer exhausted.\n" ;
break ;
}
}
}