it-swarm-tr.com

İmzasız ints ile ilgili en iyi uygulamalar nelerdir?

Her yerde imzasız ints kullanıyorum ve yapmam gerekmediğinden emin değilim. Bu veritabanı birincil anahtar kimliği sütunlarından sayaçlar, vb olabilir. Bir sayı asla negatif olmamalıdır, o zaman her zaman imzasız bir int kullanılır.

Ancak başkalarının kodundan kimse bunu yapmak gibi görünüyor fark ettim. Göz ardı ettiğim çok önemli bir şey var mı?

Düzenleme: Bu sorudan beri de C, hatalar için negatif değerler döndürmek yerine C++ istisnalar atmak yerine yaygın olduğunu fark ettim.

45
wting

Göz ardı ettiğim çok önemli bir şey var mı?

Hesaplamalar hem imzalı hem de imzasız türleri ve farklı boyutları içerdiğinde, tür tanıtımı için kurallar karmaşık olabilir ve beklenmeyen davranış yol açabilir.

Ben neden Java imzasız int türleri atlandı ana nedeni olduğuna inanıyorum.

28

Ben Michael geçerli bir noktaya sahip olduğunu düşünüyorum, ama IMO herkes her zaman int kullanmak nedeni (özellikle for (int i = 0; i < max, i++) bunu bu şekilde öğrendik. Bir ' programlama nasıl öğrenilir ' kitabındaki her örnek bir int döngüsünde for kullanıyorsa, çok az bu uygulamayı hiç sorgulayamayacak.

Diğer neden ise int 'ın uint' den% 25 daha kısa olması ve hepimizin tembel olduğumuz ... ;-)

18
Treb

Aralık bilgilerini türlere kodlamak iyi bir şeydir. Derleme zamanında makul sayıların kullanılmasını zorunlu kılar.

Birçok mimaride int -> float dönüşümleriyle başa çıkmak için özel talimatlar var gibi görünüyor. unsigned öğesinden dönüşüm daha yavaş olabilir (küçük bir miktar) .

11
Benjamin Bannier

İmzalı ve imzasız türlerin karıştırılması sizi bir acı dünyasına sokabilir. Tüm imzalanmamış türleri kullanamazsınız, çünkü negatif sayılar içeren geçerli bir aralığa sahip olan veya bir hatayı belirtmek için bir değere ihtiyaç duyan ve -1 en doğal olan şeylerle karşılaşırsınız. Net sonuç, birçok programcının tüm imzalı tamsayı türlerini kullanmasıdır.

8
David Schwartz

Kullanırım unsigned int C++ dizi dizinleri, çoğunlukla ve 0'dan başlayan herhangi bir sayaç için. Ben açıkça "bu değişken negatif olamaz" demek iyi olduğunu düşünüyorum.

7
quant_dev

Benim için türler iletişim ile ilgilidir. Açıkça imzasız bir int kullanarak bana imzalı değerlerin geçerli değerler olmadığını söylersiniz. Bu, değişken adına ek olarak kodunuzu okurken bazı bilgiler eklememe izin verir. İdeal olarak ben anonim olmayan bir tip bana daha fazlasını söylerdim, ama her yerde ints kullanmış olmanızdan daha fazla bilgi verir.

Ne yazık ki herkes kodlarının ne hakkında konuştuğuna dair çok bilinçli değil ve değerler en azından imzasız olsa bile muhtemelen her yerde ints görmenin nedeni budur.

7
daramarak

İmzalı bir int'in sınırlarına gerçekten yaklaşabilecek veya bunları aşabilecek bir tam sayı ile uğraşırken bunu önemsemelisiniz. 32 bit tamsayının pozitif maksimum değeri 2.147.483.647 olduğu için a) asla negatif olmayacağını ve b) 2.147.483.648'e ulaşacağını biliyorsanız işaretsiz bir int kullanmalısınız. Veritabanı anahtarları ve sayaçlar da dahil olmak üzere çoğu durumda, bu tür sayılara asla yaklaşmayacağım, bu yüzden işaret bitinin sayısal bir değer için mi yoksa işareti belirtmek için mi kullanıldığından endişe etmiyorum.

Şunu söyleyebilirim: imzasız bir int'e ihtiyacınız olduğunu bilmiyorsanız int kullanın.

3
Joel Etherton

Basitlik ve güvenilirlik arasında bir denge. Derleme zamanında ne kadar çok hata yakalanabilirse, yazılım o kadar güvenilirdir. Farklı insanlar ve kuruluşlar bu spektrum boyunca farklı noktalarda.

Ada'da herhangi bir yüksek güvenilirlik programlaması yaparsanız, feet cinsinden mesafe veya metre cinsinden mesafe gibi değişkenler için farklı türler bile kullanırsınız ve yanlışlıkla birini diğerine atarsanız derleyici bunu işaretler. Bu, güdümlü bir füzeyi programlamak için mükemmeldir, ancak bir web formunu doğrulıyorsanız aşırıya kaçma (cezalandırma amaçlı). Gereksinimlere uyduğu sürece her iki durumda da yanlış bir şey olması gerekmez.

3
Karl Bielefeldt

Joel Etherton'ın muhakemesine katılmaya meyilliyim, ancak tam tersi sonuca varıyorum. Gördüğüm şekilde, sayıların imzalı bir türün sınırlarına yaklaşma olasılığının düşük olduğunu bilseniz bile, biliyorum negatif sayıların olmayacağını, o zaman kullanmak için çok az neden var bir türün imzalı varyantı.

Aynı nedenle, birkaç seçili örnekte, SQL Server tablolarında BIGINT (32 bit tam sayı) yerine INTEGER (64 bit tam sayı) kullandım. Verilerin makul bir süre içinde 32 bit sınırına ulaşma olasılığı miniktir, ancak gerçekleşirse, bazı durumlarda sonuçlar oldukça yıkıcı olabilir. Sadece diller arasında türleri doğru bir şekilde eşleştirdiğinizden emin olun, aksi takdirde gerçekten tuhaf bir tuhaflık yaşayacaksınız ...

Bununla birlikte, veritabanı birincil anahtar değerleri, imzalı veya imzasız gibi bazı şeyler için gerçekten önemli değildir, çünkü kırık verileri veya bu satırlar boyunca bir şeyi el ile tamir etmedikçe, doğrudan değerle uğraşmazsınız; bu bir tanımlayıcı, başka bir şey değil. Bu durumlarda, tutarlılık muhtemelen kesin imza seçiminden daha önemlidir. Aksi takdirde, imzalanmış bazı yabancı anahtar sütunları ve imzasız olan, belirgin bir deseni olmayan - veya yine ilginç bir tuhaflık ile sonuçlanırsınız.

2
a CVn

Yer kısıtlaması olan veri depolama ve veri alışverişi bağlamlarının dışında, genellikle imzalı türleri kullanmanız önerilir. 32 bit işaretli bir tam sayının çok küçük olacağı, ancak 32 bit işaretsiz bir değerin bugün için yeterli olacağı çoğu durumda, 32 bit işaretsiz değerin de yeterince büyük olmaması uzun sürmeyecektir.

İmzasız türler kullanması gereken birincil süreler, birden çok değeri daha büyük bir değere birleştirirken (örn. Dört baytı 32 bit sayıya dönüştürürken) veya daha büyük değerleri daha küçük değerlere ayırırken (örneğin 32 bit sayıyı dört bayt olarak depolamaktır) ), veya birisinin periyodik olarak "devirmesi" beklenen bir miktar olduğunda ve bununla başa çıkması gerektiğinde (bir konut yardımcı sayacı düşünün; çoğunda okumalar arasında devrilemeyeceklerinden emin olmak için yeterli rakamlar vardır yılda üç kez okunurlarsa, ancak metrenin yararlı ömrü içinde devrilmemelerini sağlamak için yeterli değilse). İmzasız tipler genellikle yalnızca semantiklerinin gerekli olduğu durumlarda kullanılmaları için yeterli 'tuhaflığa' sahiptir.

1
supercat

Kodumu ve amacını daha açık hale getirmek için imzasız ints kullanıyorum. Hem imzalı hem de imzasız tiplerle aritmetik yaparken beklenmedik örtük dönüşümlere karşı korumak için yaptığım bir şey imzasız değişkenlerim için imzasız bir kısa (genellikle 2 bayt) kullanmaktır. Bu birkaç nedenden dolayı etkilidir:

  • İmzasız kısa değişkenleriniz ve değişmez değerlerinizle (int türünde) veya int türündeki değişkenlerle aritmetik yaptığınızda, int işaretlenmemiş değişkenin ifadeyi değerlendirmeden önce her zaman int değerine yükseltilmesini sağlar, çünkü int her zaman kısatan daha yüksek bir sıraya sahiptir . Bu, ifadenin sonucunun elbette imzalı bir int'e uyduğu varsayılarak, imzalı ve imzasız türlerle aritmetik yapan beklenmedik davranışları önler.
  • Çoğu zaman, kullandığınız imzasız değişkenler, imzasız 2 baytlık kısa bir değerin (65.535) maksimum değerini aşmaz.

Genel ilke, imzasız değişkenlerin türünün, imzalı türe yükseltmeyi sağlamak için, imzalı değişkenlerin türünden daha düşük bir sıraya sahip olması gerektiğidir. O zaman beklenmedik taşma davranışınız olmaz. Açıkçası bunu her zaman sağlayamazsınız, ancak (çoğu) çoğu zaman bunu sağlamak mümkündür.

Örneğin, son zamanlarda böyle bir şey döngü için bazı vardı:

const unsigned short cuint = 5;
for(unsigned short i=0; i<10; ++i)
{
    if((i-2)%cuint == 0)
    {
       //Do something
    }
}

'2' değişmez değeri int türündedir. Eğer imzasız bir kısa yerine imzasız bir int olsaydı, o zaman alt ifadede (i-2), 2 imzasız bir int'e yükseltilirdi (çünkü imzasız int imzalı int'den daha yüksek önceliğe sahiptir). İ = 0 ise, alt ifade (0u-2u) = taşma nedeniyle bazı büyük değerlere eşittir. İ = 1 ile aynı fikir. Ancak, i imzasız bir kısa olduğu için, int imzalı '2' ile aynı türe yükseltilir ve her şey yolunda gider.

Ek güvenlik için: uyguladığınız mimarinin int'in 2 bayt olmasına neden olduğu nadir durumlarda, imzasız kısa değişkenin uymaması durumunda aritmetik ifadedeki her iki işlenenin de imzasız int'e yükseltilmesine neden olabilir. işaretli 2 bayt int içine, ikincisi maksimum 32,767 <65,535 değerine sahiptir. (Daha fazla bilgi için https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned adresine bakın). Buna karşı korunmak için programınıza aşağıdaki gibi bir static_assert ekleyebilirsiniz:

static_assert(sizeof(int) == 4, "int must be 4 bytes");

ve int'in 2 bayt olduğu mimarilerde derlenmeyecektir.

1
AdmiralAdama