Bellek Yönetimi bölümüne ek yapıyorum. (Kitabın kağıt baskısının son hazırlıkları.)
offsetof niteliğini (property) ve align niteliğini (attribute) anlatırken aşağıdaki gibi bir işlev yazdım. Yapının bellekteki yerleşiminin nerelerinde ne kadar doldurma baytı bulunduğunu gösteriyor.
Doldurma baytlarını aza indirmenin bir yolu, üyeleri büyükten küçüğe doğru sıralı olarak tanımlamaktır. Aynı üyelere sahip oldukları halde B yapısının üyeleri A'dan daha küçüktür:
void nesneYerleşiminiYazdır(T)()
if (is (T == struct) || is (T == union))
{
import std.stdio;
import std.string;
writefln("=== '%s' nesnelerinin yerleşimi (.sizeof: %s, .alignof: %s) ===",
T.stringof, T.sizeof, T.alignof);
/* Tek satır bilgi yazar. */
void satırYazdır(size_t uzaklık, string bilgi)
{
writefln("%4s: %s", uzaklık, bilgi);
}
/* Doldurma varsa miktarını yazdırır. */
void doldurmaBilgisiYazdır(size_t beklenenUzaklık,
size_t gözlemlenenUzaklık)
{
if (beklenenUzaklık < gözlemlenenUzaklık) {
/* Gözlemlenen uzaklık beklenenden fazlaysa
* doldurma baytı var demektir. */
const doldurmaMiktarı = gözlemlenenUzaklık - beklenenUzaklık;
const bilgi = format("... %s bayt DOLDURMA", doldurmaMiktarı);
satırYazdır(beklenenUzaklık, bilgi);
}
}
/* Bir sonraki üyenin doldurma olmayan durumda nerede
* olacağı bilgisini tutar. */
size_t doldurmasızUzaklık = 0;
/* Not: __traits(allMembers) bir türün üyelerinin
* isimlerinden oluşan bir 'string' topluluğudur. */
foreach (üyeİsmi; __traits(allMembers, T))
{
mixin (format("alias üye = %s.%s;", T.stringof, üyeİsmi));
const uzaklık = üye.offsetof;
doldurmaBilgisiYazdır(doldurmasızUzaklık, uzaklık);
const türİsmi = typeof(üye).stringof;
satırYazdır(uzaklık, format("%s %s", türİsmi, üyeİsmi));
doldurmasızUzaklık = uzaklık + üye.sizeof;
}
doldurmaBilgisiYazdır(doldurmasızUzaklık, T.sizeof);
}
struct A
{
byte b;
int i; // Ortada tanımlanmış
ubyte u;
}
struct B
{
int i; // Başta tanımlanmış
byte b;
ubyte u;
}
import std.stdio;
void main()
{
nesneYerleşiminiYazdır!A();
writeln();
nesneYerleşiminiYazdır!B();
}
Çıktısı:
'=== 'A' nesnelerinin yerleşimi (.sizeof: 12, .alignof: 4) ===
0: byte b
1: ... 3 bayt DOLDURMA
4: int i
8: ubyte u
9: ... 3 bayt DOLDURMA
=== 'B' nesnelerinin yerleşimi (.sizeof: 8, .alignof: 4) ===
0: int i
4: byte b
5: ubyte u
6: ... 2 bayt DOLDURMA'
align niteliği ise değişkenlerin, kullanıcı türlerinin, ve üyelerin hizalama birimlerini belirler. Örneğin, yukarıdaki A'nın eşdeğeri olan aşağıdaki yapıda hiç doldurma baytı bulunmaz:
align (1) // Bu yapının nesnelerinin hizalama değeri (alignment)
struct C
{
byte b;
align (1) int i; // i'nin hizalama değeri
ubyte u;
}
void main()
{
nesneYerleşiminiYazdır!C();
}
Hiç doldurma baytı olmayınca nesnelerin büyüklüğü üyelerin toplam büyüklüklerine denk oluyor:
'=== 'C' nesnelerinin yerleşimi (.sizeof: 6, .alignof: 4) ===
0: byte b
1: int i
5: ubyte u'
Ancak, heyecana kapılıp her yere align(1) eklemeden önce :) C yapısının performansını denemeyi ihmal etmeyin! Hizalama biriminin bir amacı performanstır. C'nin int üyesi yukarıdaki gibi dördün katı olmayan bir adrese rastlatılırsa benim denemelerime göre %10'dan fazla hız kaybına bile neden olabilir çünkü int değerlere dördün katı olan adreslerde iseler hızlı erişilirler.
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]