Ce face alignas, alignof
Procesorul citește datele cel mai repede când ele încep la o adresă multiplu de o anumită valoare, numită aliniere. Un int de 4 octeți vrea o adresă multiplu de 4, un double multiplu de 8. alignof(tip) dă această valoare.
Din cauza alinierii, compilatorul adaugă octeți goi (padding) între membrii unei structuri, așa că sizeof unei structuri poate fi mai mare decât suma membrilor. Ordonarea membrilor de la cel mai mare la cel mai mic reduce adesea acest spațiu pierdut.
alignas(n) cere o aliniere mai mare (putere a lui 2). Se folosește la programare de nivel jos: instrucțiuni SIMD, separarea datelor folosite de fire de execuție diferite pe linii de cache diferite (64 de octeți).
Exemple
Exemplul 1: Alinierea tipurilor de bază
#include <print>
int main() {
std::println("alignof(char) = {}", alignof(char));
std::println("alignof(int) = {}", alignof(int));
std::println("alignof(double) = {}", alignof(double));
}
Rezultat
alignof(char) = 1
alignof(int) = 4
alignof(double) = 8
Exemplul 2: Padding în structuri
Ambele structuri au aceiași membri, dar în altă ordine. În prima, după fiecare char se adaugă octeți goi ca double-ul să fie aliniat la 8.
#include <print>
struct Risipitor {
char a;
double b;
char c;
};
struct Compact {
double b;
char a;
char c;
};
int main() {
std::println("Risipitor: {} octeți", sizeof(Risipitor));
std::println("Compact: {} octeți", sizeof(Compact));
}
Rezultat
Risipitor: 24 octeți
Compact: 16 octeți
Exemplul 3: Aliniere cerută cu alignas
#include <print>
struct alignas(64) Contor {
long valoare = 0;
};
int main() {
std::println("alignof(Contor) = {}", alignof(Contor));
std::println("sizeof(Contor) = {}", sizeof(Contor));
}
Rezultat
alignof(Contor) = 64
sizeof(Contor) = 64
Greșeli frecvente
- Ceri o aliniere care nu este putere a lui 2 (
alignas(12)) sau mai mică decât cea naturală a tipului. Compilatorul o refuză. - Salvezi o structură direct într-un fișier (octet cu octet) și o citești pe alt sistem. Padding-ul și alinierea pot diferi, deci datele nu se potrivesc.
Comenzi înrudite
sizeof: Dă numărul de octeți ocupați în memorie de un tip sau de o variabilă; se calculează la compilare.struct: Grupează mai multe valori într-un singur tip; ca o clasă, dar cu membri publici implicit.thread_local: Fiecare fir de execuție (thread) primește propria copie a variabilei, creată când pornește firul și distrusă la final.