Question
In C, suppose you have a function memset_16aligned that requires a pointer aligned to a 16-byte boundary. If the pointer is not 16-byte aligned, the program may crash.
How can you:
- Allocate
1024bytes of memory and ensure the pointer passed tomemset_16alignedis aligned to a 16-byte boundary? - Free the memory correctly after
memset_16alignedfinishes?
Example skeleton:
{
void *mem;
void *ptr;
/* answer a) here */
memset_16aligned(ptr, 0, 1024);
/* answer b) here */
}
Short Answer
By the end of this page, you will understand what memory alignment means in C, why some functions require aligned pointers, how to manually create aligned memory using only standard library facilities, and how to free it safely afterward.
Concept
Memory alignment means storing data at addresses that are multiples of some value, such as 8 or 16. A pointer is 16-byte aligned if its address is divisible by 16.
This matters because:
- Some CPU instructions require aligned memory.
- Some low-level functions are written for performance and assume alignment.
- Misaligned access can be slower, or on some systems, invalid.
In this question, the key challenge is that the C standard library historically does not provide a portable aligned allocator in older C versions. That means if you must use only standard library tools like malloc and free, the usual technique is:
- Allocate a little more memory than you need.
- Move the returned pointer forward until it reaches the desired alignment.
- Keep the original pointer so you can still pass it to
freelater.
The important rule is:
freemust be called with the original pointer returned bymalloc.- You must not call
freeon the adjusted aligned pointer.
If you are using modern C, aligned_alloc exists in C11, but it has its own rules and is not available everywhere. Interview questions often expect you to know the manual technique because it works with basic standard allocation functions.
Mental Model
Think of malloc as giving you a parking lot starting point, but not necessarily one lined up exactly with a painted parking space boundary.
If you need a car parked exactly on every 16th line, you:
- reserve a little extra space,
- move forward to the next correct painted line,
- remember where the parking lot really began so you can return it properly later.
So:
mem= the real start of the allocated blockptr= the adjusted, aligned address you actually use
You work with ptr, but you free mem.
Syntax and Examples
The classic manual approach in C is:
#include <stdlib.h>
#include <stdint.h>
size_t size = 1024;
size_t alignment = 16;
void *mem = malloc(size + alignment - 1);
if (mem == NULL) {
/* handle allocation failure */
}
void *ptr = (void *)(((uintptr_t)mem + alignment - 1) & ~(uintptr_t)(alignment - 1));
What this does
malloc(size + alignment - 1)allocates enough extra bytes so there will definitely be some 16-byte-aligned address inside the block.(uintptr_t)memconverts the pointer to an integer type that can safely hold an address.- Adding
alignment - 1ensures rounding goes upward. & ~(alignment - 1)clears the lower bits, producing the next aligned address.
Full example
#include
{
*mem;
*ptr;
mem = ( + );
(mem == ) {
;
}
ptr = ( *)((()mem + ) & ~());
memset_16aligned(ptr, , );
(mem);
}
Step by Step Execution
Consider this example:
#include <stdlib.h>
#include <stdint.h>
void *mem = malloc(32 + 15);
void *ptr = (void *)(((uintptr_t)mem + 15) & ~(uintptr_t)15);
Assume malloc returns an address like 1003.
Step 1: Allocate extra space
You ask for 32 + 15 = 47 bytes.
Why extra?
Because somewhere between 1003 and 1003 + 15, there must be an address divisible by 16.
Step 2: Add 15
1003 + 15 = 1018
Step 3: Round down to a multiple of 16
A multiple of 16 near 1018 is 1008.
Real World Use Cases
Aligned memory appears in real systems programming and performance-sensitive code.
Common uses
- SIMD operations: SSE, AVX, and similar instruction sets may require or benefit from aligned data.
- Image and audio processing: buffers are often aligned for vectorized operations.
- Game engines: math libraries and frame buffers may use alignment for speed.
- Networking and device I/O: some hardware interfaces expect specific alignment.
- Custom allocators: memory pools often enforce alignment for objects.
Example scenarios
- A video filter processes 16 bytes at a time using vector instructions.
- A physics engine stores vectors in aligned blocks for fast matrix math.
- A cryptography routine reads data in fixed-size aligned chunks.
Real Codebase Usage
In real projects, developers usually avoid hand-writing alignment logic everywhere. Instead, they wrap it in helper functions or use platform/library APIs.
Common patterns
Guard clauses
Always check allocation results:
mem = malloc(1024 + 15);
if (mem == NULL) {
return;
}
Encapsulating alignment in a helper
#include <stdlib.h>
#include <stdint.h>
void *align_ptr(void *p, size_t alignment) {
return (void *)(((uintptr_t)p + alignment - 1) & ~(uintptr_t)(alignment - 1));
}
This makes call sites cleaner.
Keeping both pointers
A common pattern is to store:
- the original allocation pointer for freeing
- the aligned working pointer for use
Prefer standard APIs when available
In modern code, developers may use:
Common Mistakes
1. Freeing the adjusted pointer instead of the original one
Broken code:
void *mem = malloc(1024 + 15);
void *ptr = (void *)(((uintptr_t)mem + 15) & ~(uintptr_t)15);
free(ptr); /* Wrong */
Why it is wrong:
ptrwas not returned bymalloc- calling
freeon it is undefined behavior
Correct:
free(mem);
2. Not allocating extra space
Broken code:
void *mem = malloc(1024);
void *ptr = (void *)(((uintptr_t)mem + 15) & ~(uintptr_t)15);
Why it is risky:
- rounding upward may move forward
Comparisons
| Approach | Standard | Portable | Easy to Free | Notes |
|---|---|---|---|---|
malloc only | Yes | Yes | Yes | Does not guarantee a chosen alignment like 16 bytes in older C standards |
| Manual over-allocation + adjust pointer | Yes | Yes | Yes, if you keep original pointer | Common interview solution |
aligned_alloc | C11 | Not always available in older environments | Yes | Size must be a multiple of alignment |
posix_memalign | POSIX | No, not pure standard C | Yes | Common on Unix-like systems |
Cheat Sheet
#include <stdlib.h>
#include <stdint.h>
Allocate 1024 bytes aligned to 16
void *mem = malloc(1024 + 15);
if (mem == NULL) {
/* handle error */
}
void *ptr = (void *)(((uintptr_t)mem + 15) & ~(uintptr_t)15);
Use it
memset_16aligned(ptr, 0, 1024);
Free it
free(mem);
Rules
- Allocate
size + alignment - 1 - Align with integer math using
uintptr_t - Alignment should be a power of two
- Free the original
mallocpointer, not the adjusted one - Check for before using the memory
FAQ
Does malloc already return aligned memory in C?
malloc returns memory suitably aligned for any object type, but that does not always mean it meets a specific requirement like 16-byte alignment in all contexts or older systems.
Why can I not call free(ptr) on the aligned pointer?
Because ptr is not the original pointer returned by malloc. Only the original allocation pointer may be passed to free.
Why do I need to allocate alignment - 1 extra bytes?
That guarantees there is enough room to move forward to the next aligned address without losing usable space from the requested block.
Why is uintptr_t used?
It is an unsigned integer type capable of safely holding a pointer value for address calculations.
Does this bit trick work for any alignment value?
It works when the alignment is a power of two, such as 8, 16, 32, or 64.
Is there a standard C function for aligned allocation?
Yes, aligned_alloc was added in C11. However, older code and interview questions often expect the manual method.
If I use aligned_alloc, do I still need two pointers?
Mini Project
Description
Build a small C program that allocates a 16-byte-aligned buffer, writes values into it, verifies the alignment, and then frees the memory correctly. This project demonstrates the exact pattern used in interview questions and low-level systems code.
Goal
Create and use a manually aligned 1024-byte buffer using only standard library allocation functions, then release it safely.
Requirements
- Allocate enough memory for a 1024-byte buffer plus extra bytes for alignment.
- Compute a 16-byte-aligned pointer from the original allocation.
- Verify that the computed pointer is divisible by 16.
- Write some bytes into the aligned buffer.
- Free the original pointer, not the adjusted one.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.