Şimdi Ara

C veri tipleri karmaşası

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
23
Cevap
2
Favori
1.420
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 12
Sayfaya Git
Git
sonraki
Giriş
Mesaj
  • merhaba arkadaşlar yüksek seviyeli programlama dillerinde hangi veri tipi ile değişken oluştarıyım diye bir sorun olmuyor fakat C dilinde bu böyle değil benim kafam herzaman hangi veri tipini kullanacağım diye karışmıştır "unsigned int" mi int mi kullansam kuıllansam long intmi kullansam bir türlü karar veremiyorum sizce bunu neye göre seçmeliyim kara vermekte çok zorlanıyorum yani diyeceğim o ki neye göre ve neden hangi veri tipini seçmeliyim ben genellikle herzaman hız açısından seçerim sizin fikriniz...



  • Tamamen ihtiyacına göre, aşağıdaki şema yardımcı olacaktır.

     C veri tipleri karmaşası
  • alizwel A kullanıcısına yanıt
    haklısınızda işte neye ihtiyaç duyacağımızıda kestirmek zor. kadamdaki karmaşayı daha iyi anlatmak için bir örnek vereyim örneğin "void insert(int sıra, void *val, Liste *liste)" şeklinde bir fonksiyon yazdık diyelim bu fonksiyon "val" adlı değeri listenin "sıra" adlı değişkenin değerine denk gelen sırasına ekliyor şimdi bu "sıra" adlı değişken negatif değer alırsa bu sefer tersten eklemeye başlayacak fakat tersten ekleme olayını negatif değilde pozitif sayılarlada halledebiliriz yani en sona eklemek istiyorsak "sıra" parametresine "-1" yerine listenin uzunluğunu verebiliriz burada fonksiyonun çalışma hızı şunlara bağlıdır: eğer fonksiyon negatif değerleride kabul ederse fonksiyonun hızı sadece pozitif değerlerle çalışma durumuna göre daha yavaş çalışır. bu koşulda pozitif sayılarlada negatif sayıların yaptığını yapabiliyorsak ozaman fonksiyonun daha hızlı çalışması için sadece pozitif bir sayı kabul ettirmeliyiz ve fonksiyon sadece pozitif sayıları kabul ederse "sıra" parametresinin veri tipi neden "unsigned int" değilde "int" işte bu durumda ne yapmamız gerekiyor...




  • Birkaç kb'lik bellegi ve ona kiyasla islem gücü de zayif olan bir cihazi mi kodluyorsun yani tecrübeli arkadaslar daha iyi bilecektir çok da emin konusmak istemiyorum ama ha int kullanmissin ha unsigned int kullanmissin hiz farkini anlamayacaksin ki zaten. Bence kod nasil daha düzgün okunabilir oluyorsa onu gözeterek kullan gitsin birini.

    < Bu ileti tablet sürüm kullanılarak atıldı >
  • Karakterler için -> char
    Küçük ya da büyük farketmeksizin tamsayı aritmetik için -> int veya long
    Lojik işlemler için -> unsigned
    Noktalı sayılar için -> double

    Bir sayı sadece 100'e kadar çıkıyor diye değişkeni char yapmak gereksiz (hatta yanlış). Bir sayı negatif almıyor diye unsigned yapmak ta yanlış. İstisnai durumları int ile işleyebilirsin ama unsigned ile zor. Örneğin;

    a = b < 0 ? 0 : b;
  • hocam lojik işlemler nedemek onu söylerseniz ufkum genişleyecek birde lojik işlemle ilgili bir kod örneği verirmisiniz
    ve son olarakta neden bir sayının 100'e kadar çıkıyor diye char yapmak gerkesiz ?
    aydınlatırsanız ok memnun olurum şimdiden teşekkürler
  • quote:

    Orijinalden alıntı: elektro_gadget

    Karakterler için -> char
    Küçük ya da büyük farketmeksizin tamsayı aritmetik için -> int veya long
    Lojik işlemler için -> unsigned
    Noktalı sayılar için -> double

    Bir sayı sadece 100'e kadar çıkıyor diye değişkeni char yapmak gereksiz (hatta yanlış). Bir sayı negatif almıyor diye unsigned yapmak ta yanlış. İstisnai durumları int ile işleyebilirsin ama unsigned ile zor. Örneğin;

    a = b < 0 ? 0 : b;

    Bende bu yoruma tamamen katılıyorum.


    Bununla beraber yukarda yayınlanan tabloda çoğu değer yanlış. Veya şöyle söyliyeyim; 16Bit makineye göre verilmiş değerler. 32Bit makineler çıkalı 20 sene oldu neredeyse... ve hatta artık bizim makineler hep 64Bit.

    32Bit makinede register büyüklüğü de 32bit yani 4 Byte olacağı ve temel veri tipi olan "int" de makinenin registeri büyüklüğünde olacağını düşünerek bu değerler aslında şöyle olmalı:

    char, unsigned char: 1 Byte
    short, unsigned short, short int, unsigned short int: 2 Byte
    int, unsigned int: 4 Byte <--- en hızlı ve verimli bunlar çalışır.
    float: 4 Byte
    long integer, unsigned long integer, double: 8 Byte
    long double : 10 Byte

    Bu arada ben "long int" veya "unsigned long int"yi herhangi bir dosya uzunluğunu betimlemesi dışında, malum dosyalar 2 ila 4 GB'dan daha büyük olabiliyorlar, nadir durumlarda kullanıyorum.
    Küsüratlı matematik işlemleri ve doğal sayılar kullanılıyorsa da tabiyatıyle muhakkak "double" veya "long double" kullanmak lazım... "float" burda biraz 2 arada bir derede kalıyor. Ancak yapılan iş de hız çok önemli ve sayının aldığı değerler "float" sınırları dışına taşmayacağı garantiyse o zaman "float" da kullanılabilinir elbette...




  • Yapay Zeka’dan İlgili Konular
    Daha Fazla Göster
  • cwr kullanıcısına yanıt
    öyle diyorusunuz ama bazı insanlar oknuklık için kodu çok fazla yavaşlatıyor bu benm sinirimi bozuyor niye okunaklık için performanstan bukadar ödün veriyorki tmm okunklıkta önemli ama bukadar ileri gitmek gereklimi bilmiyorum ve kodu ilk kullanımda hız farkını anlayamayız ama kod defalarca bir döngü içinde çalıştığı zaman hız farkı anlaşılabiliyor tabii her kod için demiyorum
  • Buzz Lightyear B kullanıcısına yanıt
    hocam bnm makimemde long double 16 byte linux 64 bit kullanıyorum ve işletim sistemim 64 bit olduğu halde int veri tipi 32 bit



    < Bu mesaj bu kişi tarafından değiştirildi Harun2525 -- 24 Eylül 2015; 20:41:38 >
  • Harun2525 H kullanıcısına yanıt
    O zaman gcc'nin ürettiği kod 32Bitlik kod. Benim makine de 64Bit olmasına rağmen bende hala 32Bit exelik kod derletiyorum. Ancak kullandığım derleyicide "64Bitlik exe üret" seçeneği de mevcut ancak ben kullanmıyorum.

    Senin gcc'nin de 64Bitlik linux exesi üretecek şekilde de ayarlanabiliniyor olması lazım diye tahmin ediyorum. O durumda da int 8 Byte olacaktır mesela...
  • Lojik işlem sayının bütününün aritmetik olarak bir değer ifade etmemesi (genelde), bitlerin ayrı gruplar halinde işlenmesidir. Bu gibi durumlarda standart, sade bir bit dizilimi olması gerekir. İşaretsiz türler bunu sağladığı için idealdir. Ayrıca lojik işlemlerde 16'lık tabanda çalışmak daha kolaydır. Mesela bir sayının 4, 5, 6, 7 numaralı bitlerinin sayı değerini elde etmek istiyoruz.

    unsigned a;
    ...
    int b = a >> 4 & 0x0F;

    Sağa öteleme işleminde derleyici işaretli ve işaretsiz sayılar için farklı cpu komutları üretir. İşaretli sayılarda "aritmetik öteleme" kullanır ki bu sol tarafa dolacak olan bitin, sayının negatif ya da pozitif olmasına göre değişebileceği anlamına gelir. Bitsel işlemlerde belirsiz durumlar istenmez. Misal el soldaki (msb) bitini flag olarak kullansak ve 1 yapsak sayı otomatikman negatif olur ve sağa ötelemede sol tarafa 0 yerine 1 dolar.

    unsigned ile belirsiz durum olmaz. Msb biti de diğer bitler gibidir, değeri ne olursa olsun sol tarafa 0 dolar.




  • Buzz Lightyear B kullanıcısına yanıt
    haklı olabilirsiniz bence işletim sistemi 64 bit diye işlemcinin register büyüklüğüde 64 bit olcak diye birşey yok gibi bir yargıya vardım yalnış hatırlamıyorsam 64 işletim sistemleri 32 bir makinalarada kurluyor
  • Harun2525 H kullanıcısına yanıt
    Demin baktım bu arada windows'da 64Bit exe'de de "int" 4 Byte büyüklüğünde. O kadar büyük sayılara gerek yok + diziler aşırı yer işgaline yol açar diye yine de 4Byte'da tutmuşlardır.. Hem geri kalan 32Bitlik boşluğa da başka sayı veya "instruction" yüklüyordur o şekilde kullanarak yer ve zamandan tasarruf ediliniyordur.. Gayet makul.
  • Int boyutunun register boyutu ile ayni olmasi gibi bir zorunluluk yok, derleyiciye kalmis bir sey olsa da ben henuz hic 64 bit derlemede 8 byte int cikaran derleyici gormedim. Hatta sadece pointerlarda denildigi gibi bir sinirlama var.

    Onun disinda, en verimli tip gibi bir kavram kesinlikle yok, temel veri tipleri icin zaten butun operasyonlar bir instruction cycle harcarlar.

    Her ne kadar bir deger 100u gecmeyecek diye char kullanmayin denmis olsa da, ornegin resim isleyeceginiz bir programda her renk kanalini int yerine char olarak tutarsaniz, resmi tuttugunuz array'in boyutu 4te 1ine inecek, dolayisiyla da cache'de tek seferde 4 kat daha fazla piksel bulundurabileceksiniz.

    Gunumuzde optimizasyonlarin buyuk bolumunun cache coherency uzerine oldugunu dusunurseniz inanilmaz bir kazanc. Zira, L1, L2, L3 cache'den veri okumak 3-4, 15-20, 50-60 clock cycle surerken sistem RAM'inden veri okumak 500-600 clock cycle surebiliyor.

    Verecegim diger bir ornek ise, oyunlarda double degil float kullanilmasi. Modern islemcilerde, birden cok veri uzerinde tek instructionla (SIMD, single instruction, multiple data) islem yapabiliyorsunuz. Bu instructionlari kullanabilmeniz icin islemcilerde 128 bitlik (16 byte) bir kac register bulunuyor. Oyunlarda 3d vector, matrix ve quaternion operasyonlarinin cok buyuk bolumu ayni anda pek cok toplama ve carpmadan ibaret. SIMD mimarilerini kullanarak, bu operasyonlari birkac kat hizlandirmak mumkun. Ancak, 16 byte'lik registerlara ayni anda 2 double sigdirabilirken, 4 float sigabiliyor. Dolayisiyla double yerine float kullanarak cok daha hizli islem yapabiliyoruz.

    Unsigned tipleri sayiniz hic negatif (yada pozitif) olmayacaksa tabi ki kullanin, bir degiskenin maximum degerinin 2ye katlanmasi kimseye zarar vermez.

    Sonuc olarak, veri tipleri arasindaki farklari performans oncelikli yazilimlar haricinde cok da gorebileceginizi zannetmiyorum, ve bu tarz programlarda da modern islemcilerin mimarileri dolayisiyla bu tarz secimler yapiyoruz.

    SSE kullanimi:
     C veri tipleri karmaşası



    < Bu mesaj bu kişi tarafından değiştirildi Fatih513 -- 25 Eylül 2015; 0:01:19 >




  • hocam dediklerinize baklırsa bayağı bilgili bir insansnız sanırıım ama sizin dedikleriniz elektro_gadget hocamın deidkleri ile ile ters düşüyor o negatif değer almayacak diye bir değişkene unsigned yapmak yalnış diyor siz ise tersini söylüyorsunuz yani unsigned yapabilrisiniz diyorsunuz kafam karıştı şimdi
  • Harun2525 H kullanıcısına yanıt
    Acikcasi, unsigned tiplerin var olus sebebi, adindan da anlasilacagi uzere, sadece pozitif yada sadece negatif deger almasi gereken degiskenler olusturmak.

    Negatif deger almayacak bir degiskenin unsigned olmasi kadar dogal hic bir sey yok hatta aksi yanlis olmasa da bana kalirsa eksiktir.

    Ornegin, bir array yada listenin uzunlugunu signed bir degiskende tutmanin ne gibi bir mantigi olabilir?

    Bunun disinda unsigned kullanmak zorunda oldugumuz durumlar da var, ornegin ustte verdigim ornekteki piksel degerlerini signed bir char degiskende tutarsaniz 255 degeri veremeyeceksiniz.

    Kasitli olarak unsigned kullanmamak gerektigini ilk defa bu baslikta duyuyorum, en kotu kodunuz daha anlasilir olur.



    < Bu mesaj bu kişi tarafından değiştirildi Fatih513 -- 25 Eylül 2015; 1:35:15 >
  • Fatih513 kullanıcısına yanıt
    Evet kesinlikle.

    Ben nedense hep "int" register boyutu büyüklüğünde olur diye hatırlıyordum öyle değilmiş. Hatta öyle ki windowsda 64Bit exe'de bile pointer boyutu 8 yerine 4Byte maalesef. Ancak Linux 64Bit de int 4 byte iken pointerlar çok daha fazla adresleme kapasitesine sahip olan "8 Byte" boyutundaymış. Ki zaten Linux da C ve C++ programlarında tek seferde GB boyutunda array alanı ayırabilmekle bu özelliğininin ipuçlarını vermişti.

    Verimli tip derken bende "int"nin 4 adet "char/byte" şeklinde yorumlanmasını kastetmiştim bu arada. Forum olduğu için yazdığım şeyi biraz kısa tutmak istedim ancak aynı bu konuya yani int'nin 4byte char şeklinde yorumlanması hadisesine bende bu forumda yazdığım önceki mesajlarımdan birkaçında değinmiştim.

    float hadisesine de tamamen katılıyorum. Bende oyunlarda özellikle DirectX ve OpenGL programlama arayüzlerinde neredeyse sürekli float kullanıldığını bilerek yukarda o yorumu yazmıştım. Vaktiyle 2003 senesinde "DirectX 8" APIsi kullanarak, ki şu ana kadar gelmiş geçmiş en kötü ve kullanışsız DirectX APIsi olarak bilinir, güzel bir hem 2D hem de 3D destekleyen gayet güzel ve kullanışlı bir oyun motoru yazmıştım. O zamanlar işte bu float işlerine haddinden fazla maruz kalmıştım maalesef. Yazdığım oyun motorunda da temel ışıklandırmaya kadar bir çok şeyi halletmiştim ancak daha detaylı gölgelendirme, ışıklandırma hadiselerinde usanıp bırakmıştım işi... Matris işlemlerinden gına gelmişti artık... Özellikle grafik programlama da herşey float dediğiniz gibi. Ama ben artık bıktım float'dan, yazdığım programlarda hıza öyle çok gerek kalmayan APIde kullanmadığım için hep double kullanıp geçiyorum artık...

    Forumda bu konulardan haberdar olan, bilen kişi sayısının artması sevindirici, çok selamlar ve teşekkürler.




  • index'lerde ben genelde signed kullanıyorum, herhangi bir geri dönüş değeri -1 ise hata oluştu veya istenen eleman bulunamadı gibi bir anlam içersin diye. Ama bununla beraber elbette array ve dizi boyutlarının signed olmasının çok da bir mantığı yok ama değişik durumlara göre eksi değer döndürebilme özgürlüğü de (eğer 2GB'dan fazla sayıyla işlem yapılmayacaksa) makul bence.

    Yani duruma göre değişiyor, çok da bir problem olmaz herhalde. Ancak çok büyük değerlerde özellikle 2GBdan büyük değerlerle çalışmak ihtimali de varsa o zaman elbette signed/unsigned hadiselerine dikkat etmek lazım.
  • Javada unsigned yok mesela, adamlar gerekli görmemiş. Maksimum değeri ikiye katlamaktan daha önemli şeyler var. C' deki birçok fonksiyon sadece pozitif tamsayı döndürmesine rağmen dönüş değeri int tir. Bunun sebebi oluşabilecek istisnaları programcıya en anlaşılır yoldan bildirmek. 0'ın üstü uygun değer, 0'ın altı hata kodu gibi. Parametre alırken de signed değerler çok işe yarar, 0'ın üstü kabul, 0'ın altı varsayılan değer atamak gibi...

    Dizi indeksi olarak int kullanmadığınız zaman derleyici (gcc) sizi uyarır, int kullan der. Dizinin ortasına bir işaretçi konumlandırırsanız negatif indeks ile geriye sarabilirsiniz.

    Bol bol kod okumak lazım. Bu adamlar niçin sadece pozitif değer almasına rağmen heryerde int kullanmış acaba diye düşünmek lazım.

    Dizi olayına girmeyi unutmuşum orada haklısınız. Cache miktarı kısıtlı olduğundan küçük boyutlu diziler daha hızlı çalışabilir ama pratikte pek işe yaramaz bu. Burada birinci öncelik bellek kullanımını düşürmektir.

    Birşey daha ekleyeyim. Eğer 31 bit yetmiyor diye 32 bit kullanıyorsanız muhtemelen 32 bit te yetmeyecektir.




  • İşlemcilerde simd ve fpu ayrı donanımlar. Örneğin arm işlemcilerdeki fpu float işlemlerini 1 cycle da yaparken double 2 cycle. Önemsiz bir hız kaybı ile hassasiyeti ikiye katlamış oluyorsunuz. x86 da muhtemelen hepsi 1 cycle dır.

    Simd ayrı bir olay, aynen verdiğimiz dizi örneği gibi. Tek kullanım ayrı dizi kullanımı ayrı. Büyük veri kümeleri işlerken her cycle ın hesabını yapmak gerekebilir tabi.
  • 
Sayfa: 12
Sayfaya Git
Git
sonraki
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.