'Uint' ve 'short' veri tiplerinin standart int (32) 'den daha uygun olduğu durumlar nelerdir?


24

Kapasite ve değerlerdeki temsil edebilecekleri arasındaki farkı anlıyorum ancak uygun olup olmadığına bakılmaksızın insanlar her zaman kullanıyor gibi görünüyor Int32. Hiç kimse imzasız sürümü ( uint) kullanıyor olsa da, olumsuz olamayacak bir değeri (belki de bir veritabanı kaydının kimliğini temsil etmek için) çoğu zaman daha iyi uysa bile. Ayrıca, hiç kimse short/Int16değerin gerekli kapasitesine bakılmaksızın kullanıyor gibi görünmüyor .

Objektif daha iyi kullanılmasına nerede, orada durumlar vardır uintya short/Int16ve eğer öyleyse, bunlar hangi mı?


13
Popülerlik, her zaman yazılım tasarım kararlarını değerlendirmek için uygun bir ölçüm değildir. Bir uygulamanın popüler olması, sizin özel uygulamanız için uygun bir uygulama olduğu ya da iyi bir uygulama olduğu anlamına gelmez.
Robert Harvey,


1
Kısa cevap, programcıların imzalı anlamlara alıştığını ve imzasız türlerle (ve dolayısıyla imzasız anlambilimiyle) uğraşırken bile bunları üstlenme eğiliminde olduklarını düşünüyorum. Çoğu kişi, programcının tembel ya da eğitimsiz olduğunu düşünür, ancak söz konusu programcı aslında çok eğitimli ve çok dikkatli olabilir ve ince tuzaklardan kaçınmak ister. İsterseniz, soundsoftware.ac.uk/c-pitfall-unsigned ve anteru.net/2010/05/17/736 adreslerine bakın .
Theodoros Chatzigiannakis

İmzasız bir sayıda, işaret nullpozitif veya negatif olandan daha fazladır. Bunu asla olumsuz olamayacak veya her zaman olumlu olamayacak bir şey olarak düşünürseniz, sonuçlara şaşıracaksınız (ve çoğu zaman sinirleneceksiniz) çünkü bu şekilde çalışmaz, özellikle / ile karşılaştırıldığında / imzalı değerler.
Adam D. Ruppe

1
Tecrübelerime göre, C dilinde programlanmış birçok programcı, halen bu günlerde, GB bellek ve depolama alanı için baytları önemseme eğilimindedir.
user1451111

Yanıtlar:


25

İntegral türleri doğru kullanan kişilerle çalışmadığınız, kendi deneyimlerinizle renklendirilmiş bir perspektife atıf yaptığınızdan şüpheleniyorum. Bu yaygın bir durum olabilir, ancak benim de sık sık insanların bunları doğru kullandığı benim deneyimim.

Bunun yararı, türlerin şimdiye kadar tel üzerinden mi yoksa diske mi gönderildiğine bağlı olarak, bellek alanı ve işlemci zamanı, muhtemelen GÇ alanıdır. İmzasız tipler, imkansız olan bazı işlemleri yapmamanız için derleyici kontrolleri sağlar, ayrıca gerekli olan yerlerde daha yüksek performans için daha küçük boyutta tutarken mevcut aralığı genişletir.

Doğru beklediğiniz gibi kullanılmasıdır - Bildiğiniz zaman kesin kullanmadan kalıcı (do kesinlik olmadan sınırlamak ya da yoktur edecek daha sonra pişman).

  • Asla makul olmayacak bir şeyi temsil etmeye çalışıyorsanız ( public uint NumberOfPeople) işaretsiz bir tür kullanın.
  • Asla makul ölçüde 255 ( public byte DamagedToothCount) den büyük bir şey göstermeye çalışıyorsanız , bir bayt kullanın.
  • Makul bir şekilde 255'ten büyük, ancak hiçbir zaman önemli sayıda bin olmayan bir şeyi temsil etmeye çalışıyorsanız , bir kısa kullanın ( public short JimmyHoffasBankBalance).
  • Yüz binlerce, hatta milyonlarca, hatta birden fazla milyara ulaşamayacak bir şeyi temsil etmeye çalışıyorsanız, bir int ( public int HoursSinceUnixEpoch) kullanın .
  • Kesin olarak bu rakamın sınırsız büyük bir değeri olabileceğini biliyorsanız veya birden fazla milyara sahip olabileceğini düşünüyorsanız, ne kadar milyarlarca olduğundan emin değilsiniz, en iyisi ne kadar uzun. Eğer yeterince büyük değilse, ilginç bir probleminiz vardır ve rastgele hassas nümeriklere ( public long MyReallyGreatAppsUserCountThisIsNotWishfulThinkingAtAll) bakmaya başlamanız gerekir .

Bu akıl yürütme imzalı, imzasız ve çeşitli ebat ve diğerleri arasında seçim yaparken kullanılabilir, sadece gerçekte temsil ettiğiniz verilerin mantıksal gerçekleri hakkında düşünün.


11
+1, telefonun "sayıların" sayı değil, sayı dizeleri ve isteğe bağlı olarak biçimlendirme olduğunu açıkça belirtmem gerekir. Bunun farkında gibi görünüyorsun, ama biz kötü bir örnek olmak istemiyoruz, değil mi? Ayrıca, bazı değerlerin aralığını keyfi olarak sınırlama, kısa görüşlü bir antipattern - intsorun alanının gerçekten de değeri sınırladığı bir gerçek olduğunu bilmediğiniz sürece her yerde - hiçbir banka hesapları 33K sterline sınırlamak istemez (ve eğlenceyi düşünmek istemez) bu taşma olduğunda…!).
amon

3
Yeni Yaşam Hedefi: Banka hesabımın ayrılmaz tipini aşan oldukça fazla taslak.
recursion.ninja

11
İmzasız türleri belirli yerlerde, örneğin aritmetik imzalı ve imzasız arasında karıştırırken kullanmamanın iyi nedenleri vardır. Bkz in imzasız ilişkin en iyi uygulamalar nelerdir? .

19
Buradaki akıl yürütmeye katılmıyorum. İmzasız türler genellikle çıkarma işlemine alışkınsanız çıkarma ve beklenmedik olmalarından dolayı bir hatadır (tutarlı bir şekilde çalışırlar ancak "her zaman pozitif" değildir). Onları kullanmak için çok özel bir nedeniniz yoksa onlardan kaçınırdım. Ayrıca, neden bayt vs kısa vs int boyutu önemlidir? Yapılar bu üyeleri veya dizileri belirli bir hizaya getireceği için, çoğu zaman yer kazanmazsınız bile. Bir bayt, yalnızca boyut gerçekten önemliyse (özellikle de gördüğüm C # koduna göre pek mümkün değilse) ya da özellikle 255'te bir şey için sarmalamayı istiyorsanız.
Adam D. Ruppe

4
"yarar hafıza alanı ve işlemci zamanıdır" ... Küçük tiplerin aslında CPU zamanından tasarruf sağlayacağı bir durum görmüyorum . Tamsayılı işlemler hiçbir zaman makine boyutlarındaki türlerden daha hızlı gerçekleşmez , yani CPU ile ilgili olarak kullanabileceğiniz kadar long. Bellek tasarrufu elbette önbellek verimliliğini artırarak dolaylı olarak zaman kazandırabilir, ancak OTOH küçük tiplerle uyum sorunlarını dolaylı olarak zaman alabilir.
14:14

16

Elbette, uintya shortda kullanmanın daha iyi olduğu durumlar var Int16. Veri aralığınızın, bu değişken türünün sınırlarına uyacağını bildiğiniz zaman , o türü kullanmanız tamamdır.

Belleğin kısıtladığı ortamlarda veya çok sayıda nesneyle çalışırken, en küçük boyut değişkenini kullanmak mantıklı olabilir. Örneğin, bir milyona karşılık gelen elemanlar intvs. için boyut bakımından önemli bir fark vardır short.

Çoğu zaman, bu, aşağıdaki nedenlerden biri veya birkaçı nedeniyle gerçek kodda olmaz:

  • Veri kısıtlamaları zamanından önce bilinmiyordu
  • Veri kısıtlamalarının sağlam olmadığı veya büyük olasılıkla değiştirildiği bilinen bir ihtimal vardı.
  • Fonksiyonu daha geniş bir veri aralığı ile tekrar kullanma ümidi vardı.
  • Geliştirici kısıtlamaları düşünmek için zaman almadı
  • Bellek tasarrufu, daha küçük bir değişken türü kullanarak haklı göstermek için önemli değildi.

Çok daha olası nedenler var, ama buna bağlı kalıyorlar: Farklı bir değişken tipine karar vermek ve kullanmakla ilgili zaman bunu haklı çıkarmak için yeterli bir yarar sağlamadı.


8

C de, tamsayı promosyonu içermeyen bağlamlarda , işaretsiz değerlerin "sarma" soyut cebirsel bir halkanın üyeleri olarak davranacağı belirtildi (yani, herhangi bir X ve Y için, XY, Y'ye eklendiğinde X'in vereceği benzersiz bir değer verecek) ), işaretli tamsayı türleri, hesaplamalar belirli bir aralıkta kaldığında tamsayılar gibi davranırken ve hesaplamalar bunun ötesine geçtiğinde hiç bir şey yapmasına izin verilirken. Bununla birlikte, C #'daki sayısal anlam tamamen farklıdır. İşaretli bir sayısal bağlam içerisindeyken, hem işaretli hem de işaretsiz türler, hesaplamaların aralık dahilinde kalması koşuluyla tamsayılar gibi davranırlar OverflowException; denetlenmeyen bir bağlamda, ikisi de cebirsel halkalar gibi davranır.

Genellikle herhangi bir veri türünü kullanmaktan daha az Int32zaman harcayacağınız zamandan daha küçük olanı, küçük saklama veya taşıma için bir şeyler paketlemek veya açmak gerekir. Bir kişinin yarım milyar pozitif sayı kaydetmesi gerekiyorsa ve hepsi 0 ile 100 arasında olacaksa, dört yerine her biri bir bayt kullanmak, 1,5 gigabayt depolama tasarrufu sağlayacaktır. Bu büyük bir tasarruf. Bununla birlikte, bir kod parçasının toplam birkaç yüz değeri saklaması gerekirse, her birini dörtten ziyade bir bayt yapmak, yaklaşık 600 baytlık bir tasarruf sağlar. Muhtemelen uğraşmaya değmez.

İmzasız türlerle ilgili olarak, gerçekten yararlı oldukları tek zaman, bilgi değişimi yaparken veya sayıları parçalara böldüğünüz zamandır. Örneğin, bir kişinin 96 bitlik tamsayılarda matematik yapması gerekiyorsa, hesaplamaları, imzasız üçlü 32 bitlik tamsayılardan oluşan gruplarda, imzalı tamsayılardan çok daha kolay olacaktır. Aksi takdirde, imzalı bir 32 veya 64 bitlik değerin aralığının yetersiz olacağı pek çok durum yoktur, ancak aynı boyuttaki imzasız değer yeterli olacaktır.


4

İmzasız türleri kullanmak genellikle kötü bir fikirdir, çünkü hoş olmayan şekillerde taşarlar. x = 5-6aniden kodunuzda bir timebomb. Bu arada, imzasız türlerin yararları da tek bir ekstra hassasiyete kayıyor ve bu bit sizin için buna değerse, bunun yerine neredeyse kesinlikle daha büyük bir tür kullanıyor olmalısınız.

Daha küçük bir türün mantıklı olabileceği kullanım durumları vardır, ancak bellek kullanımı konusunda endişe duymadığınız veya aktarım veya önbellek verimliliği için bir veri paketi ya da başka endişeleriniz için bir veri toplama ihtiyacı duymadığınız sürece, genellikle daha küçük bir tür kullanmanın faydası olmaz . Üstelik, birçok mimaride, bu türlerin kullanımı daha yavaştır , böylece küçük bir maliyet getirebilirler.


3
C'de, imzalı taşma imzasız taşma durumundan bile daha kötüdür (çünkü imzasız bir kilometre sayacı gibi dönmesi belirtilirken tanımsız davranışıdır). OTOH, üzerinde işaretlenmiş / düşük debili uygulamada imzasız malzemeden çok daha az yaygındır.
Kevin,

Doğru, ancak imzalı taşma genellikle daha açık ve tahmin edilebilirdir.
Jack Aidley

Genellikle katılıyorum, ama modern derleyiciler optimize olabileceğini, örneğin, farkında olmak gerekiyor i+1>iiçine 1eğer idiğer kötü davranış bir bütün ana ile birlikte imzalanır. İmzasız taşma, köşe bir durumda bir hataya neden olabilir. İmzalanmış taşma, programınızın tamamını anlamsız hale getirebilir .
Kevin,

@JackAidley Söylediklerinin hiçbir anlamı olmadığından eminim, çünkü 5-6 aynı bit kalıbını veriyor, imzası olmasa da olmasa da.
Ingo

@Ingo: Bit modellerine ne sıklıkla bakıyorsunuz? Önemli olan bit paterninin anlamı , hangi bitlerin açık veya kapalı olduğudur.
Jack Aidley

2

Genellikle, .NET türleriyle ilgilenirken, özellikle unutulmuş ve muhtemelen soruya teğet olur, CLS Uyumluluğu . Her tür .NET Framework üzerinde oluşturulan tüm dillerde bulunmayabilir.

C # dışındaki diller tarafından tüketilecek bir kod yazıyorsanız ve bu kodun olabildiğince çok .NET dili ile birlikte çalışmasının garanti edilmesini istiyorsanız, tür kullanımınızı CLS Uyumlu olanlarla sınırlandırmanız gerekir.

Örneğin, VB.NET'in (7.0 ve 7.1) önceki sürümleri işaretsiz tamsayıları ( UInteger) desteklemiyordu :

http://msdn.microsoft.com/en-us/library/aa903459(v=vs.71).aspx

İmzasız tamsayılar CLS uyumlu değildir ve sınıf kütüphane tüketicinizin kim olacağından emin değilseniz, dikkatli kullanılmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.