January 27, 2018

Kitapta nesne üyelerinin yerleşimlerini aralarındaki doldurma baytlarıyla birlikte gösteren bir kod var:

http://ddili.org/ders/d/bellek_yonetimi.html#ix_bellek_yonetimi..offsetof

Oradaki işlevi üyelerin kapsadıkları baytları Unicode karakterleriyle gösterecek biçimde biraz geliştirdim:

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);

   /* Üyeyle (veya doldurma baytlarıyla) ilgili bilgi yazdırır.
    *
    *  başlangıç: Üyenin nesne içindeki yeri (offset)
    *  miktar: Üyenin kaç baytlık olduğu (sizeof)
    *  bilgi: Yazdırılacak olan bilgi
    */
   void üyeYazdır(size_t başlangıç, size_t miktar, string bilgi) {
       assert(miktar != 0);

       /* Üyenin bayt kapsamını görselleştirmek için bu satırda
          kullanılması gereken karakteri döndürür. */
       auto çizgiKarakteri(size_t satır) {
           if (miktar == 1) {
               assert(satır == 0);
               return '╶';
           } else {
               if (satır == 0) {
                   return '┌';
               } else if (satır == miktar - 1) {
                   return '└';
               }
               else {
                   return '│';
               }
           }
       }

       // Bilginin ortalanmış olarak görünmesi için kullanılan satır numarası
       const bilgiSatırıNumarası = (miktar - 1) / 2;
       foreach (satır; 0 .. miktar) {
           writef("%4s %s", başlangıç + satır, çizgiKarakteri(satır));
           if (satır == bilgiSatırıNumarası) {
               writef(" %s, %s bayt", bilgi, miktar);
           }
           writeln();
       }
   }

   /* 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;
           üyeYazdır(beklenenUzaklık, doldurmaMiktarı, "DOLDURMA");
       }
   }

   /* 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));

       // Bir sonraki üyeyi yazdırmadan önce varsa doldurma bilgisini yazdır
       const uzaklık = üye.offsetof;
       doldurmaBilgisiYazdır(doldurmasızUzaklık, uzaklık);

       // Şimdi bu üyeyi yazdır
       const türİsmi = typeof(üye).stringof;
       const miktar = üye.sizeof;
       üyeYazdır(uzaklık, miktar, format("%s %s", türİsmi, üyeİsmi));

       doldurmasızUzaklık = uzaklık + miktar;
   }

   // Varsa son üyeden sonraki doldurma bilgisini yazdır
   doldurmaBilgisiYazdır(doldurmasızUzaklık, T.sizeof);
}

struct A {
   byte b;
   int i;
   ubyte u;
   string s;
   byte b2;
   double d;
}

void main() {
   nesneYerleşiminiYazdır!A();
}

'
=== 'A' nesnelerinin yerleşimi (.sizeof: 48, .alignof: 8) ===
0 ╶ byte b, 1 bayt
1 ┌
2 │ DOLDURMA, 3 bayt
3 └
4 ┌
5 │ int i, 4 bayt
6 │
7 └
8 ╶ ubyte u, 1 bayt
9 ┌
10 │
11 │
12 │ DOLDURMA, 7 bayt
13 │
14 │
15 └
16 ┌
17 │
18 │
19 │
20 │
21 │
22 │
23 │ string s, 16 bayt
24 │
25 │
26 │
27 │
28 │
29 │
30 │
31 └
32 ╶ byte b2, 1 bayt
33 ┌
34 │
35 │
36 │ DOLDURMA, 7 bayt
37 │
38 │
39 └
40 ┌
41 │
42 │
43 │ double d, 8 bayt
44 │
45 │
46 │
47 └
'
Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]