When you call C’s malloc, is there any guarantee about what the first few low order bits will be? If you’re writing a compiler/interpreter for a dynamic language but want to have fixnums of the form bbbbbbbb bbbbbbbb . . . bbbbbbb1 (where b is a bit) and pointers of the form bbbbbbbb bbbbbbbb . . . bbbbbbb0 (or vice versa), is there any way to guarantee that malloc will return pointers that fit with such a scheme?
Should I just allocate two more bytes than I need, increment the return value by one if necessary to fit with the bit scheme, and store the actual pointer returned by malloc in the second byte so that I know what to free?
Can I just assume that malloc will return a pointer with zero as the final bit? Can I assume that an x86 will have two zero bits at the end and that an x64 will have four zero bits at the end?
C doesn’t guarantee anything about the low order bits being zero only that the pointer is aligned for all possibly types. In practice 2 or 3 of the lowest bits will probably be zero, but do not count on it.
You can ensure it yourself, but a better way is to use something like posix_memalign.
If you want to do it yourself you need to overallocate memory and keep track of the original pointer. Something like (assuming you want 16-byte alignment, could be made generic, not tested):
void* my_aligned_malloc16(size_t sz) { void* p = malloc(sz + 15 + 16); // 15 to ensure alignment, 16 for payload if (!p) return NULL; size_t aligned_addr = ((size_t)p + 15) & (~15); void* aligned_ptr = (void*) aligned_addr; memcpy(aligned_ptr, &p, sizeof(void*)); // save original pointer as payload return (void*)(aligned_addr + 16); // return aligned address past payload } void my_aligned_free16(void* ptr){ void** original_pointer = (void**)( ((size_t)ptr) - 16 ); free(*original_pointer); }As you can see this is rather ugly, so prefer using something like
posix_memalign. Your runtime probably has a similar function if that one is unavailable, e.g.memalign(thanks @R..) or _aligned_malloc when using MSVC.