9 Mart 2016 Çarşamba

Data Alignment

C++
Data Alignment yazısına taşıdım.

alignof metodu
alignof yazısına taşıdım.

alignas metodu
alignas ile bir verinin nasıl align edilmesini istediğimizi belirtiriz. POD içindeki bir alan yüzünden fazlaca yer israf ediliyorsa kullanılabilir. Örnek:

struct st
{
    short a; //2 byte
    int *b; // 8 byte (64 bit işletim sistemi)
    char ch;//1 byte
};

11 byte kullanılması gerekirken, 8 byte alan yüzünden 8'in katı olan 24 byte'lık alan ayırılır.

Daha az alan kullanmak için nasıl align edilmesi gerektiği alignas ile belirtirlir.
struct alignas(char) aligned_struct
{
    short a;
    int *b;
    char ch;
};
Bu durumda 12 byte'lık alan ayırılır. VS 2012 alignas'i desteklemiyor!

offsetof metodu
struct içindeki alanın kaçıncı byte'tan başladığını belirtir. Örnek:
struct Test
{
 char data1;
 char data2;
}
cout << offsetof (Test,data1); // 0 verir
cout << offsetof (Test,data2); // 2 verir
struct Test {short data1, short data2, double data3} ile offsetlerin şöyle başladığı gözlemlenebilir.
struct Test
{
  short data1; //2
  short data2; //2
  char[4] pad1;//4
  double data3;//8
}

offsetof macrosu sadece standard layout olan sınıflarda kullanılabilir. Bu macro ile encapsulation kırılabilir. Örnekte private olan bir nesnenin value alanına erişilebiliyor.
#include<iostream>
using namespace std;

class A
{
    int value;
 public:
    A(){value = 1;}
    ~A(){}

    void print(){cout << value << endl;}
 };

int main()
{
    A a;
    int* p = (int*)(&a);
    *p = 20;
    a.print();//output is 20.
}
__attributed__((packed))
gcc ile kullanılır. Padleme yapma anlamına gelir. Şöyle yaparız.
struct __attribute__((__packed__)) structure
{
   int id1;
   char name;
   int id2;
   char c;
   float percentage;
};

pragma pack
Microsoft ve gcc platformunda kullanılır. Pragma'ya verilen sayıdan büyük olan alanlar verilen sayıya göre hizalanır. Eğer alan pragma sayısından küçükse bir şey yapılmaz.

Verinin 1 byte olarak hizalanması için  örnek:
#pragma pack(push, 1)
typedef struct {
    unsigned char __reserved : 1;
    unsigned char dont_fragment : 1;
    unsigned char more_fragment : 1;
    unsigned short fragment_offset : 13; 
} ipv4_fragmenting;
#pragma pack(pop)
Şöyle de yapılabilir.
#pragma pack(1)
typedef struct {
    unsigned char __reserved : 1;
    unsigned char dont_fragment : 1;
    unsigned char more_fragment : 1;
    unsigned short fragment_offset : 13; 
} ipv4_fragmenting;
#pragma pack()
Bir başka örnekte veri 4 byte olarak hizalanıyor.
#pragma pack(push,4)
struct  MyStruct
{  
    uint32_t i1;        /* offset=0  size=4 */
    uint32_t i2;        /* offset=4  size=4 */
    uint16_t s1;        /* offset=8  size=2 */
    unsigned char c[8]; /* offset=10 size=8 */
    uint16_t s2;        /* offset=18 size=2 */
    uint16_t s3;        /* offset=20 size=2 */
                        /* offset=22 padding=2 (needed to align MyStruct) */
} ; // total size is 24

C#
Interop ile C++ kodlarını çağırırken struct'lara müdahale etmek mümkün.

MarshalAs Anotasyonu
Bu anotasyon managed ve unmanaged kod arasında, belleğin nasıl dönüştürüleceğini UnmanagedType enumeration ile kontrol eder.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct PSTSensor
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string name;
    public int id;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public float[] pose;
    public double timestamp;
}
Tiplerin Büyüklüğü
Dikkatli olunması gereken nokta boolean tipi. Boolean 1 byte değildir. Diğer tiplerde sorun çıkmaz. Mesela aşağıdaki byte[] 3 byte büyüklüğündedir.
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct struct1
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] values;
}
Çıktı olarak 3 alırız.
Console.WriteLine("sizeof array of bytes: "+Marshal.SizeOf(typeof(struct1)));
Ancak boolean array 12 byte büyüklüğündedir
[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct struct2
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public bool[] values;
}
Çıktı olarak 12 alırız.
Console.WriteLine("sizeof array of bools: " + Marshal.SizeOf(typeof(struct2)));

UnmanagedType çeşitleri
Örnek:

ByValTStr
C tarzı karakter arrayleri için kullanılır.

ByValArray
Primitive bir tip array'i tanımlamak için kullanılır.


Hiç yorum yok:

Yorum Gönder