9.14. stdalign.h
: Hizalama
Bu dosyada _Alignas
bellek sınıfı belirteci ve _Alignof
işleci için
daha basit eşanlamlılar tanımlanır:
#define alignas _Alignas #define alignof _Alignof #define __alignas_is_defined 1 #define __alignof_is_defined 1
Nesnelerin Bellekte Hizalanması
Her nesne tipi, bu tipteki nesnelere bellek üzerinde
belirli bir hizalama uygular, yani bu tipteki nesnelerin saklanabileceği
bellek adreslerinin türünü de belirler. Bu adres türü; herhangi bir bellek
adresi, sadece çift (yani iki ile bölünebilen) adresler, sadece dörde,
sekize vs. bölünebilen adresler gibi bir özelliktir. Bir tipin
hizalanması, o tipten iki nesneyi bellekte
saklarken aralarındaki en düşük mesafeye eşit olan bayt sayısı olarak ifade
edilebilir. Tiplerin hizalama değerleri bir sistemden diğerine
değişiklik gösterebilir, ancak bunlar her zaman ikinin üsleri şeklinde
olur: 1, 2, 4, 8, 16 gibi. Başka bir tipin hizalamasından daha büyük bir değere
sahip bir hizalamanın diğerinden
daha katı
olduğu söylenir. char
tipindeki nesneler en düşük
katılıktaki
hizalamaya sahiptirler; bu değer çoğu sistemde
1’e eşittir.
C Standardında bir tipin hizalamasını belirlemek, yani değerini elde etmek
için _Alignof
işleci kullanılır. Bir nesne tanımında
hizalamayı belirtmek, yani değiştirmek için ise _Alignas
bellek sınıfı anahtar sözcüğü kullanır.
_Alignof
işleci tiplere uygulanır ve tıpkı
sizeof
işleci gibi (stddef.h
veya diğer başlık dosyalarında tanımlanan) işaretsiz bir tamsayı tipi
olan size_t
tipinde değişmez bir değer verir. Örneğin,
_Alignof(int)
ifadesi,
genelde 4
değerine sahip, int
tipinin hizalamasını verir. Aşağıdaki program bölümü, belli başlı
tiplerin sizeof
ve _Alignof
değerlerini verecektir:
printf("%zu %zu %zu %zu %zu %zu, %zu %zu %zu\n", sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), sizeof(char *), sizeof(float), sizeof(double), sizeof(long double)); printf("%zu %zu %zu %zu %zu %zu, %zu %zu %zu\n", _Alignof(char), _Alignof(short), _Alignof(int), _Alignof(long), _Alignof(long long), _Alignof(char *), _Alignof(float), _Alignof(double), _Alignof(long double));
Yukarıdaki kod, sisteminizde belki her iki çıktı satırı
için tamamen aynı değerleri verebilir. Ancak, bu her zaman geçerli değildir.
Örneğin, bazı 32 bitlik Windows sistemlerinde,
long double
tipinin boyu 12 bayt olmasına rağmen,
hizalaması 4 bayttır.
_Alignof(max_align_t)
’den küçük veya eşit bir
hizalama değerine
temel hizalama
denir. Tüm temel tipler (ve gösterge tipleri) temel bir hizalamaya sahiptir.
stddef.h
başlık dosyasında
tanımlanmış olan max_align_t
tipinin hizalaması,
dinamik bellek ayırma dahil, her bağlamda desteklenir. Ek olarak, bir ortamda
genişletilmiş hizalamalar
olarak da bilinen _Alignof(max_align_t)
’den daha
büyük hizalamalar da desteklenebilir.
Bir nesne _Alignas
belirteciyle tanımlandığında,
tipinin gerektirdiğinden daha sıkı (yani daha yüksek değerli)
bir hizalamaya sahip olabilir.
_Alignas
’ın argümanı, aşağıdaki
örneklerde olduğu gibi, geçerli bir hizalama değeri olan bir değişmez
tamsayı veya bir tip olabilir:
_Alignas(4) short s1; _Alignas(double) float f1;
Birinci örnekte s1
değişkeni 4’e
bölünebilen bir adrese yerleştirilecektir. İkinci örnekte f1
değişkeni double
’ın hizalama değerine
(bizim sistemimizde 8) bölünebilen bir adrese yerleştirilecektir.
_Alignas(tip)
ile
_Alignas(_Alignof(tip))
aynı anlama gelir.
Bir başka örnek olarak, aşağıdaki iki yapının tanımına bakalım:
struct y1 { char c1, c2; long l; } y1d; struct y2 { char c1, c2; _Alignas(32) long l; } y2d;
Kullanılan sistemde long
’un
8 bayt olduğunu varsayalım. Birinci değişkenin (y1d
) boyu,
yani sizeof
değeri, 16 bayt olacaktır:
Bir yapının en son üyesinin hizalandığı adres (örnekte 8) artı boyu (örnekte 8)
ve yapının hizalama değerine tamamlanmak sureti ile yapının boyu belirlenir.
Birçok uygulamada, bir yapının hizalama değerinin en büyük hizalamaya sahip
olan üyesi ile aynı olduğunu söyleyebiliriz (örnekteki ilk yapı değişkeni
için long
’un hizalama değeri, yani 8).
Aynı nedenlerden dolayı, örnekteki ikinci yapı değişkeninin
(y2d
) boyu 64 bayt, hizalaması 32 bayttır.
Bir yapı üyesinin yapının başına göre bellekte ne kadar ileride
olduğunu belirlemek için stddef.h
başlık dosyasında
tanımlanmış olan offsetof
makrosunu kullanabilirsiniz.
Örneğin, offsetof(struct y1, l)
’nin
değeri 8, offsetof(struct y2, l)
’nin
değeri ise 32’dir.