Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to align pointer

Tags:

c++

How do I align a pointer to a 16 byte boundary?

I found this code, not sure if its correct

char* p= malloc(1024);

if ((((unsigned long) p) % 16) != 0) 
{
     unsigned char *chpoint = (unsigned char *)p;        
     chpoint += 16 - (((unsigned long) p) % 16);
     p = (char *)chpoint;
}

Would this work?

thanks

like image 981
Chebz Avatar asked Jun 12 '11 05:06

Chebz


People also ask

What is an aligned pointer?

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.

What is Align function in C++?

alignas specifier(C++11) specifies that the storage for the variable should be aligned by specific amount. aligned_storage. (C++11)(deprecated in C++23) defines the type suitable for use as uninitialized storage for types of given size.

What does 4 byte aligned mean?

For instance, in a 32-bit architecture, the data may be aligned if the data is stored in four consecutive bytes and the first byte lies on a 4-byte boundary. Data alignment is the aligning of elements according to their natural alignment.


4 Answers

C++0x proposes std::align, which does just that.

// get some memory
T* const p = ...;
std::size_t const size = ...;

void* start = p;
std::size_t space = size;
void* aligned = std::align(16, 1024, p, space);
if(aligned == nullptr) {
    // failed to align
} else {
    // here, p is aligned to 16 and points to at least 1024 bytes of memory
    // also p == aligned
    // size - space is the amount of bytes used for alignment
}

which seems very low-level. I think

// also available in Boost flavour
using storage = std::aligned_storage_t<1024, 16>;
auto p = new storage;

also works. You can easily run afoul of aliasing rules though if you're not careful. If you had a precise scenario in mind (fit N objects of type T at a 16 byte boundary?) I think I could recommend something nicer.

like image 191
Luc Danton Avatar answered Sep 18 '22 05:09

Luc Danton


Try this:

It returns aligned memory and frees the memory, with virtually no extra memory management overhead.

#include <malloc.h>
#include <assert.h>

size_t roundUp(size_t a, size_t b) { return (1 + (a - 1) / b) * b; }

// we assume here that size_t and void* can be converted to each other
void *malloc_aligned(size_t size, size_t align = sizeof(void*))
{
    assert(align % sizeof(size_t) == 0);
    assert(sizeof(void*) == sizeof(size_t)); // not sure if needed, but whatever

    void *p = malloc(size + 2 * align);  // allocate with enough room to store the size
    if (p != NULL)
    {
        size_t base = (size_t)p;
        p = (char*)roundUp(base, align) + align;  // align & make room for storing the size
        ((size_t*)p)[-1] = (size_t)p - base;      // store the size before the block
    }
    return p;
}

void free_aligned(void *p) { free(p != NULL ? (char*)p - ((size_t*)p)[-1] : p); }

Warning:

I'm pretty sure I'm stepping on parts of the C standard here, but who cares. :P

like image 29
user541686 Avatar answered Sep 19 '22 05:09

user541686


In glibc library malloc, realloc always returns 8 bytes aligned. If you want to allocate memory with some alignment which is a higher power 2 then you can use memalign and posix_memalign. Read http://www.gnu.org/s/hello/manual/libc/Aligned-Memory-Blocks.html

like image 27
phoxis Avatar answered Sep 21 '22 05:09

phoxis


posix_memalign is one way: http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_memalign.html as long as your size is a power of two.

The problem with the solution you provide is that you run the risk of writing off the end of your allocated memory. An alternative solution is to alloc the size you want + 16 and to use a similar trick to the one you're doing to get a pointer that is aligned, but still falls within your allocated region. That said, I'd use posix_memalign as a first solution.

like image 28
alexras Avatar answered Sep 22 '22 05:09

alexras