Kodumu ve amacını daha net hale getirmek için imzasız girdiler kullanıyorum. Hem imzalanmış hem de imzasız türlerle aritmetik işlem yaparken beklenmedik örtük dönüşümlere karşı korunmak için yaptığım bir şey, imzasız değişkenlerim için imzasız kısa (genellikle 2 bayt) kullanmak. Bu birkaç nedenden dolayı etkilidir:
- İmzasız kısa değişkenleriniz ve değişmezler (int türündeki) veya int türündeki değişkenlerle aritmetik yaptığınızda, bu, imzasız değişkenin ifadeyi değerlendirmeden önce her zaman bir int değerine yükseltilmesini sağlar; . Bu, ifadenin sonucunun elbette imzalı bir int değerine uyduğu varsayılarak, imzalı ve imzasız türlerle aritmetik işlem yapan herhangi bir beklenmeyen davranışı önler.
- Kullandığınız imzasız değişkenler çoğu zaman, imzasız 2 baytlık kısa bir değerin (65,535) maksimum değerini aşmaz
Genel ilke, imzasız değişkenlerinizin türünün, imzalı türe promosyonu 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ışına sahip olmazsınız. Açıkçası bunu her zaman sağlayamazsınız, ancak (çoğu) bunu sağlamak çoğu zaman mümkündür.
Örneğin, son zamanlarda bazı döngü için böyle bir şey vardı:
const unsigned short cuint = 5;
for(unsigned short i=0; i<10; ++i)
{
if((i-2)%cuint == 0)
{
//Do something
}
}
'2' değişmezi int türündedir. İmzasız bir kısa yerine imzasız bir int olsaydım, o zaman alt ifadede (i-2) 2 işaretsiz bir int olarak terfi ederdi (çünkü imzasız int imzalı int'den daha yüksek önceliğe sahipti). Eğer i = 0 ise, alt-ifade eşittir (0u-2u) = taşma nedeniyle bazı büyük değerler. İ = 1 ile aynı fikir. Ancak, işaretsiz bir kısa olduğu için, int imzalı olan '2' kelimesiyle aynı tipte terfi eder ve her şey yolunda gider.
Daha fazla güvenlik için: Uyguladığınız mimarinin 2 byte olmasına neden olduğu nadir durumlarda, bu, işaretsiz kısa değişkenin uyuşmadığı durumlarda aritmetik ifadedeki her iki işlenin de imzasız int'ye yükseltilmesine neden olabilir İkincisi en fazla 32,767 <65,535 değerinde olan imzalı 2 baytlık int. (Daha fazla ayrıntı için bkz. Https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned ). 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");
int 2 byte olan mimarilerde derlenmez.
for(unsigned int n = 10; n >= 0; n --)
(sonsuz döngüler)