Alignment adalah persyaratan bahwa alamat memori suatu objek harus kelipatan tertentu. Misalnya, int di x86-64 memiliki alignment 4 byte—alamat harus habis dibagi 4. CPU dapat membaca int yang ter-align dengan satu instruksi, tetapi int yang tidak ter-align mungkin memerlukan dua instruksi atau memicu alignment fault pada arsitektur tertentu. C11 menyediakan _Alignas untuk memaksa alignment yang lebih besar dan _Alignof (alias alignof) untuk menanyakan alignment tipe. Header <stdalign.h> menyediakan alias alignas/alignof. Pada chapter ini kita akan memeriksa alignment berbagai tipe dan mengalokasikan buffer dengan alignment khusus lewat aligned_alloc.
Memeriksa Alignment dengan alignof #
Operator alignof(T) mengembalikan alignment requirement tipe T dalam byte. Operator ini adalah alias alignof untuk _Alignof (disediakan <stdalign.h>).
#include <stdio.h>
#include <stdalign.h>
#include <stdint.h>
int main(void) {
/* _Alignof / alignof: query alignment requirement */
printf("alignof(char) = %zu\n", alignof(char));
printf("alignof(short) = %zu\n", alignof(short));
printf("alignof(int) = %zu\n", alignof(int));
printf("alignof(double) = %zu\n", alignof(double));
printf("alignof(int64_t)= %zu\n", alignof(int64_t));
/* _Alignas: paksa alignment lebih besar */
_Alignas(16) int x = 42;
printf("alamat x (harus kelipatan 16): %p\n", (void *)&x);
printf("alamat &x mod 16 = %zu\n", (size_t)((uintptr_t)&x % 16));
/* Struct dengan alignment default */
struct Vec4 {
float v[4];
};
printf("sizeof(Vec4) = %zu, alignof(Vec4) = %zu\n",
sizeof(struct Vec4), alignof(struct Vec4));
/* Variabel struct dengan alignment 32 */
_Alignas(32) struct Vec4 vec;
printf("alamat vec (mod 32) = %zu\n", (size_t)((uintptr_t)&vec % 32));
return 0;
}Output yang Dihasilkan:
alignof(char) = 1
alignof(short) = 2
alignof(int) = 4
alignof(double) = 8
alignof(int64_t)= 8
alamat x (harus kelipatan 16): 0x7fffe72caff0
alamat &x mod 16 = 0
sizeof(Vec4) = 16, alignof(Vec4) = 4
alamat vec (mod 32) = 0Mari kita telaah baris-baris kode di atas:
- Baris 7-11 (
alignof(char), dst.): menanyakan alignment tipe primitif.charmemiliki alignment 1 (boleh di alamat mana pun),int4 (harus kelipatan 4),double8. Nilai-nilai ini berbeda per arsitektur—di ARM 32-bit lama,doublebisa ber-alignment 4. - Baris 14 (
_Alignas(16) int x = 42;): memaksa alignmentxmenjadi 16, lebih besar dariintaslinya (4). Compiler akan menempatkanxdi alamat yang habis dibagi 16. - Baris 15-16 (cetak alamat dan modulo): verifikasi bahwa alamat
&xhabis dibagi 16. Pada output, modulo 0 menunjukkan alignment terpenuhi. - Baris 19-22 (
struct Vec4 { float v[4]; };): struct berisi 4 float (4 byte masing-masing) = 16 byte total. Alignment struct adalah alignment dari field dengan alignment terbesar, yaitufloat= 4. - Baris 25 (
_Alignas(32) struct Vec4 vec;): variabel struct dengan alignment 32—lebih besar dari alignment default struct (4). Berguna bila struct akan dipakai di SIMD yang mensyaratkan alignment 32 byte (AVX).
Alokasi Aligned dengan aligned_alloc #
C11 menyediakan aligned_alloc(alignment, size) di <stdlib.h> untuk mengalokasikan blok memori dengan alignment yang ditentukan. Syaratnya: size harus kelipatan alignment.
#include <stdio.h>
#include <stdlib.h>
#include <stdalign.h>
#include <stdint.h>
/* aligned_alloc: alokasi buffer dengan alignment kuat */
int main(void) {
size_t alignment = 64; /* cacheline size typical x86 */
size_t count = 16; /* jumlah elemen */
size_t bytes = count * sizeof(int);
/* Round up bytes ke kelipatan alignment (syarat aligned_alloc) */
size_t aligned_bytes = ((bytes + alignment - 1) / alignment) * alignment;
int *buf = aligned_alloc(alignment, aligned_bytes);
if (!buf) { perror("aligned_alloc"); return 1; }
printf("alignment = %zu, bytes = %zu (rounded)\n", alignment, aligned_bytes);
printf("alamat buf = %p\n", (void *)buf);
printf("alamat mod alignment = %zu\n", (size_t)((uintptr_t)buf % alignment));
/* Inisialisasi dan cetak */
for (size_t i = 0; i < count; i++) buf[i] = (int)(i + 1);
printf("buf[0..3] = %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);
free(buf);
return 0;
}Output yang Dihasilkan:
alignment = 64, bytes = 64 (rounded)
alamat buf = 0x561bd3252040
alamat mod alignment = 0
buf[0..3] = 1 2 3 4Fungsi aligned_alloc menerima dua parameter: alignment dan ukuran. Pada contoh, kita mengalokasikan buffer 64 byte dengan alignment 64—sesuai dengan cacheline size pada x86-64. Buffer aligned berguna untuk SIMD (AVX-512 mensyaratkan 64 byte), DMA transfer, dan komunikasi dengan hardware tertentu.
Kapan Alignment Penting #
- SIMD (SSE/AVX): instruksi vector mensyaratkan data ter-aligned 16/32/64 byte. Akses tidak ter-aligned memicu general protection fault.
- DMA transfer: hardware DMA sering memerlukan alamat kelipatan 4 atau 8 byte.
- Atomic operations: beberapa operasi atomic pada tipe besar (misalnya
int128_t) memerlukan alignment alami tipe tersebut. - Menghindari false sharing: pada multi-threading, menempatkan variabel yang sering diakses berbeda thread di cacheline berbeda mengurangi koherensi cache.