Zarovnání (C11)
Jednou z funkcí nízké úrovně jazyka C je schopnost určit přesné zarovnání objektů v paměti, aby bylo možné využít maximální výhody hardwarové architektury.
Procesory čtou a zapisují paměť efektivněji, když ukládají data na adrese, která je násobkem velikosti dat. Například 4 bajtové celé číslo se přistupuje efektivněji, pokud je uloženo na adrese, která je násobkem 4. Pokud data nejsou zarovnaná, procesor pro přístup k datům pracuje s více výpočty adres.
Ve výchozím nastavení kompilátor zarovná data na základě jeho velikosti: char
na hranici 1 bajtů, short
na 2 bajtové hranici, int
long
a float
na 4 bajtové hranici, double
na 8 bajtové hranici atd.
Kromě toho můžete zlepšit výkon mezipaměti tím, že zarovnáte často používaná data s velikostí čáry mezipaměti procesoru. Řekněme například, že definujete strukturu, jejíž velikost je menší než 32 bajtů. Pokud chcete zajistit efektivní ukládání všech instancí struktury do mezipaměti, můžete použít zarovnání 32 bajtů.
Obvykle se nemusíte starat o zarovnání. Kompilátor obvykle zarovná data na přirozených hranicích založených na cílovém procesoru a velikosti dat. Data se zarovnají až na 4 bajtové hranice na 32bitových procesorech a 8 bajtů na 64bitových procesorech. V některých případech ale můžete dosáhnout vylepšení výkonu nebo úspor paměti zadáním vlastního zarovnání pro datové struktury.
Klíčové slovo _Alignof
C11 slouží k získání upřednostňovaného zarovnání typu nebo proměnné a _Alignas
k zadání vlastního zarovnání pro proměnnou nebo uživatelem definovaný typ.
Makra pohodlí alignof
a alignas
, definované v <stdalign.h>
, mapovat přímo na _Alignof
a _Alignas
, v uvedeném pořadí. Tato makra odpovídají klíčovým slovům používaným v jazyce C++. Použití maker místo klíčových slov jazyka C proto může být užitečné pro přenositelnost kódu, pokud sdílíte jakýkoli kód mezi těmito dvěma jazyky.
alignas
a _Alignas
(C11)
Použijte alignas
nebo _Alignas
zadejte vlastní zarovnání pro proměnnou nebo uživatelem definovaný typ. Lze je použít na strukturu, sjednocení, výčet nebo proměnnou.
Syntaxe alignas
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Poznámky
_Alignas
nelze použít v deklaraci typedef, bitového pole, funkce, parametru funkce nebo objektu deklarovaného pomocí specifikátoru register
.
Zadejte zarovnání, které je mocninou dvou, například 1, 2, 4, 8, 16 atd. Nepoužívejte hodnotu menší než velikost typu.
struct
a union
typy mají zarovnání rovnou největšímu zarovnání libovolného člena. Bajty odsazení se přidají do rozsahu, struct
aby byly splněny požadavky na zarovnání jednotlivých členů.
Pokud v deklaraci existuje několik alignas
specifikátorů (například struct
s několika členy, které mají odlišné alignas
specifikátory), bude zarovnání struct
alespoň hodnoty největšího specifikátoru.
alignas
příklad
V tomto příkladu se používá praktické makro alignof
, protože je přenosné do jazyka C++. Chování je stejné, pokud používáte _Alignof
.
// Compile with /std:c11
#include <stdio.h>
#include <stdalign.h>
typedef struct
{
int value; // aligns on a 4-byte boundary. There will be 28 bytes of padding between value and alignas
alignas(32) char alignedMemory[32]; // assuming a 32 byte friendly cache alignment
} cacheFriendly; // this struct will be 32-byte aligned because alignedMemory is 32-byte aligned and is the largest alignment specified in the struct
int main()
{
printf("sizeof(cacheFriendly): %d\n", sizeof(cacheFriendly)); // 4 bytes for int value + 32 bytes for alignedMemory[] + padding to ensure alignment
printf("alignof(cacheFriendly): %d\n", alignof(cacheFriendly)); // 32 because alignedMemory[] is aligned on a 32-byte boundary
/* output
sizeof(cacheFriendly): 64
alignof(cacheFriendly): 32
*/
}
alignof
a _Alignof
(C11)
_Alignof
a jeho alias alignof
vrátí zarovnání v bajtech zadaného typu. Vrátí hodnotu typu size_t
.
Syntaxe alignof
alignof(type)
_Alignof(type)
alignof
příklad
V tomto příkladu se používá praktické makro alignof
, protože je přenosné do jazyka C++. Chování je stejné, pokud používáte _Alignof
.
// Compile with /std:c11
#include <stdalign.h>
#include <stdio.h>
int main()
{
size_t alignment = alignof(short);
printf("alignof(short) = %d\n", alignment); // 2
printf("alignof(int) = %d\n", alignof(int)); // 4
printf("alignof(long) = %d\n", alignof(long)); // 4
printf("alignof(float) = %d\n", alignof(float)); // 4
printf("alignof(double) = %d\n", alignof(double)); // 8
typedef struct
{
int a;
double b;
} test;
printf("alignof(test) = %d\n", alignof(test)); // 8 because that is the alignment of the largest element in the structure
/* output
alignof(short) = 2
alignof(int) = 4
alignof(long) = 4
alignof(float) = 4
alignof(double) = 8
alignof(test) = 8
*/
}
Požadavky
Zkompilovat pomocí /std:c11
.
Windows SDK 10.0.20348.0 (verze 2104) nebo novější Nejnovější sadu SDK si můžete stáhnout ze sady Windows SDK . Pokyny k instalaci a použití sady SDK pro vývoj pro C11 a C17 najdete v tématu Instalace podpory C11 a C17 v sadě Visual Studio.
Viz také
/std
(Určení standardní verze jazyka)
C++ alignof
a alignas
Zpracování kompilátoru zarovnání dat