Forum: D Programlama Dili RSS
Endian Karmaşası
Avatar
zekeriyadurmus #1
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Endian Karmaşası
int veri türünde 4 değeri 00 00 00 04 şeklinde saklanırken
short verit türünde 4 değeri 04 00 şeklinde saklanıyor.

Bunun karmaşası neden var? İleride bu tarz verilerin değişmeyeceğinin bir garantisi var mı ?
Bunlarla ilgili karmaşaya düşmemek için ne yapmak lazım?

Php deki pack işlevini D de yazmaya çalışıyorum ama bu dediğim sorunla karşılaştı şimdilik :)

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #2
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
union Bint(T) {
    T i;
    char[T.sizeof] c;
};
 
int isBigEndian(T)(){ // 00 01 => Starts from right.
    auto bint = Bint!T(0x01);
    return bint.c[T.sizeof - 1] == 1; 
}

Şöyle bir çözüm buldum. Daha iyi bir yöntem var mıdır?

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
zekeriyadurmus:
int veri türünde 4 değeri 00 00 00 04 şeklinde saklanırken
short verit türünde 4 değeri 04 00 şeklinde saklanıyor.

Emin misin?
import std.stdio;
 
void main()
{
    int i = 0x01020304;
    baytlarınıGöster(i);
 
    short s = 0x0102;
    baytlarınıGöster(s);
}
 
void baytlarınıGöster(T)(ref T değişken)
{
    const ubyte * baş = cast(ubyte*)&değişken;
 
    writefln("tür    : %s", T.stringof);
    writefln("değer  : %s", değişken);
    writefln("adres  : %s", baş);
    writef(  "baytlar: ");
 
    writefln("%(%02x %)", baş[0 .. T.sizeof]);
 
    writeln();
}
Benim Intel işlemcimdeki çıktısı:

tür    : int
değer  : 16909060
adres  : 7FFF23B19538
baytlar: 04 03 02 01

tür    : short
değer  : 258
adres  : 7FFF23B1953C
baytlar: 02 01


İleride bu tarz verilerin değişmeyeceğinin bir garantisi var mı ?

Teoride, programın ileride hangi soncul ortamda çalışacağını bilemezsin. Örneğin, gelecekteki zamanda int 01 04 03 02 diye bile saklanabilir. (Değeri yine de 0x01020304 olur). Pratikte, öyle şey hiçbir zaman olmayacak. :) Ya küçük soncul ya büyük soncul...

Bunlarla ilgili karmaşaya düşmemek için ne yapmak lazım?

std.bitmanip modülünde soncullukla ilgili işlevler var.

core.bitop içinde bayt değiş tokuş eden bswap var.

Ali
Avatar
Salih Dinçer #4
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #2
Eskiden bir başlık açmıştım. Burada, Ali hocam D'nin (sanırım derleme anında) bilinen bir alias'dan bahsetmişti: Endian.littleEndian

Oradan varsayılan olarak tanımlı sorgulama yapılabiliyor. Ayrıca C standartlarında verilerin bellekte nasıl durduğunu öğrenebiliyorduk. GET ve SET ile ilgili işlevler hatırlıyorum.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #5
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #3
Evet az önce kontrol ettim değilmiş öyle ama o halde benim pack fonksiyonunun çalışmaması lazım. Kafam karıştı.

Şimdi elimde bir int ve ushort değeri var "Nn" değerine göre packliyorum bunları (ikiside aynı endian tipinde php.net sitesine göre)  ve ushort değerini ters çevirmeden packlediğim için sıkıntı yaratıyordu çalışmıyordu program bende buna istinaden ikisinin farklı olduğunu zannettim.

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #6
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #4
http://dlang.org/phobos/std_system.html#.endian

Evet buradaymış Salih hocam. Şu pack işine bir daha baksam iyi olur.

Şimdi anladım :) o int olarak gelen big endian sandığım veri aslında big endian değilmiş ama ben onu oluştururken ona göre oluşturuyormuşum :)

ip2int diye acemice bir fonksiyonum var
uint ip2int(string b){
    char[4] ret;
    auto spl = b.split(".");
    if(spl.length != 4) throw new Exception("Invalid IP address.");
    foreach(i, a; spl) ret[i] = to!ubyte(a);
    return *cast(uint*) ret.ptr;
}

Burada ben onu big endian değil little endian olarak çevirmişim o yüzden de hiç sorun yaşamamışım :)

Zekeriya
Bilgi meraktan gelir...
Bu mesaj zekeriyadurmus tarafından değiştirildi; zaman: 2014-04-08, 16:02.
Avatar
Salih Dinçer #7
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #4
Şuydu sanırım: http://www.tysos.org/svn/trunk/tload/tloadefi/msun/src/mat…

Ama zaten D'nin kendi olanağı var. Özel çözüm üretmeye gerek yok :)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #8
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Şu an bazı kavramları karıştırdım kusura bakmayın :) little big birbirine girdi birbirlerinin yerine kullandım galiba ama birkaç güne tam anlamıyla bu kavramlar yerleşirler diye düşünüyorum.

Daha önce adını çok duymuştum ama bunların sorunu ile karşılaşmak ancak nasip oldu :)
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #9
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Burada http://stackoverflow.com/questions/461742/how-to-convert-a… aşağıdaki açıklamayı buldum.
WARNING: the integers resulting from the accepted answer will be wrong, because IP addresses are in network order (big-endian), while ints are little-endian on most systems. So you must reverse the bytes before converting. See my answer for correct conversions. Also, even for IPv4, an int can't hold addresses bigger than 127.255.255.255, e.g. the broadcast address, so use a uint. –  Saeb Nov 12 '12 at 20:00

Şimdi benim tanımladığım ip2int doğru endian tipinde bu açıklamaya göre o zaman değiştirmesem de olur ama olası karmaşayı önlemek amacıyla bir struct içerisinde farklı bir tür gibi mi tanımlasam? Bu sayede o veriyi pack işlevine attığımda tekrardan ters dönüp işleri karıştırmaz.

Zekeriya
Bilgi meraktan gelir...
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-21, 13:09:01 (UTC -08:00)