SORU
22 Mart 2015, Pazar


Sadece "int" karşı imza daha özel ya da özel boyutu türleri kullanmalıyım?

32-bit hem de altında derleniyor destekler little VM for a programming language C uygulanan ve 64-bit mimarileri ve iki C ve C var .

Temiz iş çıkar gibi birçok uyarılar mümkün olduğunca etkin bir derleme yapmaya çalışıyorum. CLANG_WARN_IMPLICIT_SIGN_CONVERSION, açtığımda yeni uyarılar bir çağlayan olsun.

int karşı açıkça işaretsiz türler ve kullanmak için iyi bir strateji yapmak istiyorum veya açık olanlar bulunur. Şimdiye kadar, sorun bu stratejinin ne olması gerektiğine karar yaşıyorum.

Yerel değişkenler ve parametreler gibi şeyler için onları kullanarak, çoğunlukla int karıştırma ve yapılar—neden alanları için dar tip kullanarak örtülü dönüşüm sorunları bir sürü bu kesinlikle doğru.

Açıkça yığın içinde nesneleri için bellek kullanımını kontrol etme fikri hoşuma gitti çünkü yapı alanları için daha özel boyutta türleri kullanmayı seviyorum. Ayrıca, hash tabloları, karma zaman imzasız taşma güveniyorum, eğer karma tablo boyutu uint32_t olarak saklanıyorsa güzel bir şey.

Ama, eğer daha özel bir tür kullanınher yerdeHizmetçi ve bir labirent her yerde atmalarını kendimi buluyorum.

Diğer projeleri C ne yaparsınız?

CEVAP
23 Mart 2015, PAZARTESİ


Sadece kullanma int Her yerde çevrim gereksinimini en aza indirir beri cazip görünebilir, ama bilmeniz gereken birkaç potansiyel tuzaklar vardır:

  • int beklenenden daha kısa olabilir.Olsa bile, çoğu masaüstü platformlarında, int genellikle 32 bit the C standard only guarantees a minimum length of 16 bits. Kodunuzu hiç sayıları 2'den daha büyük olabilir16−1 = 32,767, hatta geçici değerler için? Eğer öyleyse, int kullanmayın. (long bir yerine kullanmak isteyebilirsiniz; long en az 32 bit olması sağlanır.)

  • long bile her zaman yeterli olmayabilir.Özellikle, bir dizi uzunluğu (veya char bir dizi olan bir dize) long uyan garantisi yok. Bu size_t (veya eğer imzalı bir fark gerekiyorsa ptrdiff_t,) kullanın.

    Özellikle, a size_t is defined to be large enough to hold any valid array index, int Bir ise veya bile long bir olmayabilir. Böylece, örneğin, yineleme üzerinde bir dizi, döngü sayacı (başlangıç / bitiş değerleri) genellikle bir size_t, en azından sürece emin olabilirsiniz ki bu dizi yeterince kısa için daha küçük bir türü için çalışır. (Ama dikkatli zaman geriye doğru yineleme: for(size_t i = n-1; i >= 0; i--) sonsuz bir döngüye kadar size_t imzasız! Kullanarak i != SIZE_MAX i != (size_t) -1 iş olsa da; */while *27 bir döngü kullanmak gerekir, ama bu durumda dikkat n == 0!)

  • int imzalanır.Özellikle, bu demektir int overflow is undefined behavior. Eğer hiç risk değerleri olabilir meşru taşması, kullanmayın int; unsigned int (ya da unsigned long uintNN_t) yerine.

  • Bazen, sadece sabit bit uzunluğunda lazım.Eğer belirli bir uzunlukta tamsayı gerektiren bir ABİ, ya da / dosya yazma okuma biçimi ile arayüz varsa, o zaman bunu kullanmak için gereken süre. (Tabii ki, böyle durumlarda, aynı zamanda endianness, ve bu yüzden bazen el ile veri bayt bayt zaten ambalaj başvurmak zorunda kalabilir gibi şeyler hakkında endişelenmenize gerek olabilir.)

O dedi, orada da bir sebep için kullanmaktan kaçının sabit uzunlukta türleri her zaman: sadece int32_t garip yazın her zaman, ama zorlama derleyici için her zaman kullan 32-bit tamsayı değil her zaman en iyi, özellikle platformlarda nerede yerli int boyutu olabilir, diyelim ki, 64 bit. Sanaolabilirkullanın ki, C99 int_fast32_t ama bu türü daha da garipleşti.


Böylece, burada maksimum güvenlik ve taşınabilirlik için benim kişisel öneriler:

  • Rahat kullanım için kendi tamsayı türlerini tanımlamakortak başlık dosyasında şöyle bir şey:

    #include <limits.h>
    typedef int i16;
    typedef unsigned int u16;
    #if UINT_MAX >= 4294967295U
      typedef int i32;
      typedef unsigned int u32;
    #else
      typedef long i32;
      typedef unsigned long i32;
    #endif
    

    Türü Tam Boy, yeterince büyük oldukları sürece önemi yok nerede hiçbir şey için bu tür kullanın. Bu tür isimler verdim önerilen her ikisi de kısa ve öz belgeleyen, bu yüzden onlar kolay olmalı için kullanılan atmalarını nerede gerekli, ve en aza indirmek risk hatalar nedeniyle kullanan bir çok-dar tip.

    Olup u32 u16 türleri tanımlanan yukarıdaki garantili en azından geniş olarak unsigned int ve böylece güvenle kullanılabilirler hakkında endişelenmenize gerek kalmadan onları promoted to int and causing undefined overflow behavior.

  • O ve başka bir tamsayı türleri arasında çevrim tüm dizi boyutları ve dizin oluşturma için size_t kullanın, ama dikkatli olun. Eğer çizgi birçok türü sevmiyorsun diye isteğe bağlı olarak, typedef daha uygun bir takma isim için de.

  • Bit belirli sayıda taşma kabul hesaplamalar için, ya da açık ve yukarıda & ile bitmasking tanımlanan uintNN_t ya da sadece kullanın 47* / u32 *kullanın. Eğer emin olun int; yapmanın bir yolu, beklenmedik bir terfi karşı kendinizi korumak için uintNN_t, kullanmayı tercih ederseniz, bir makro gibi

    #define u(x) (0U   (x))
    

    güvenle örneğin yazalım gereken:

    uint32_t a = foo(), b = bar();
    uint32_t c = u(a) * u(b);  /* this is always unsigned multiply */
    
  • Belirli bir tamsayı uzunluğu gerektiren dış ABİs için, daha özel bir türü, örneğin tanımlayın:

    typedef int32_t fooint32;  /* foo ABI needs 32-bit ints */
    

    Yine, bu tür adı kendini belgeleyen, büyüklüğü ve amacı açısından önemlidir.

    Eğer ABİ olabilir aslında gerektirir, ki, 16 veya 64-bit in yerine bağlı olarak, platform ve/veya derleme zamanı seçeneklerini değiştirebilirsiniz tür tanımı için maç (ve yeniden yazmak için sadece fooint) - ama o zaman gerçekten yapmak lazım dikkatli olmak ne zaman sen at bir şey için ya da bu tür, çünkü belki taşma beklenmedik bir şekilde.

  • Eğer kodunuzu belirli bitlengths gerektiren kendi yapılarını ya da dosya biçimleri varsa, o Eğer harici bir ABİ olsa da, tam olarak özel türleri düşünün. Ya da sadece uintNN_t yerine kullanabilirsin ama kendi belgelerine biraz bu şekilde kaybedersin.

  • Tüm bu türleri için de kolay sınırları kontrol etmek için _MIN 58 *ilgili sabitleri tanımlamak için unutma. Bu bir sürü iş gibi gelebilir, ama gerçekten sadece tek bir başlık dosyasında birkaç satır.

Son olarak, tamsayı matematik, özellikle taşmaları ile dikkatli olun. Örneğin, iki farkı unutmayınnbitlik imzalı tamsayı bir uyum olmayabilirn-bit int. (Bir haline geldin-bitimzasızeğer negatif olmayan; ama imzasız bir türü için giriş dökme vurgulamak gerekir ki biliyorsan intöncetanımsız davranış önlemek için onların fark alarak!) Benzer şekilde, iki tamsayı (ikili arama gibi) ortalamasını bulmak için, avg = (lo hi) / 2 ziyade avg = lo (hi 0U - lo) / 2 örneğin; eski halinde toplam taşarsa kıracak kullanmayın.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • 07cadikiz07

    07cadikiz07

    17 EKİM 2007
  • merumputdotcom

    merumputdotc

    24 ŞUBAT 2012
  • UCBerkeley

    UCBerkeley

    3 Mayıs 2006