Standart C Programlama Dili


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.