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
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 (veyachar
bir dizi olan bir dize)long
uyan garantisi yok. Busize_t
(veya eğer imzalı bir fark gerekiyorsaptrdiff_t
,) kullanın.Özellikle, a
size_t
is defined to be large enough to hold any valid array index,int
Bir ise veya bilelong
bir olmayabilir. Böylece, örneğin, yineleme üzerinde bir dizi, döngü sayacı (başlangıç / bitiş değerleri) genellikle birsize_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 kadarsize_t
imzasız! Kullanaraki != SIZE_MAX
i != (size_t) -1
iş olsa da; */while
*27 bir döngü kullanmak gerekir, ama bu durumda dikkatn == 0
!)int
imzalanır.Özellikle, bu demektirint
overflow is undefined behavior. Eğer hiç risk değerleri olabilir meşru taşması, kullanmayınint
;unsigned int
(ya daunsigned 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ş olarakunsigned int
ve böylece güvenle kullanılabilirler hakkında endişelenmenize gerek kalmadan onları promoted toint
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ımlananuintNN_t
ya da sadece kullanın 47* /u32
*kullanın. Eğer emin olunint
; yapmanın bir yolu, beklenmedik bir terfi karşı kendinizi korumak içinuintNN_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.
Git: liste sadece "izlenmeyen&quo...
Nasıl "düzgün" JavaScript öz...
Kullanarak " koyuyorsun;sayfa özel...
&Quot nedir;@Özel" Objective-C?...
&Quot;çift karma&; bir şifre sadece bi...