C'de otomatik tür dönüşümü "alışılmış aritmetik dönüşümler" ilkesine göre çalışır. Farklı işaretlerde (signed/unsigned) tanımlanmış sayıların bir ifadede yer alması durumunda, şu kurallar doğrultusunda bir dönüşüm gerçekleşir:
Tehlikeli aritmetik örneği:
int a = -1; // signed unsigned int b = 1; printf("%d\n", a < b); // her zaman false, çünkü a çok büyük bir unsigned'a dönüştürülür
Sonuç: -1, unsigned'a dönüştüğünde çok büyük pozitif bir sayıya dönüşür.
Hatırlanması gerekenler:
Soru: (int)(unsigned)-1 ifadesi ne sonuç verecek?
Beklenen yanlış cevap: "-1, çünkü -1 ve int'e dönüştürüyoruz."
Doğru cevap:
(unsigned)-1 ifadesinde önce -1'in unsigned'a dönüşümü (32 bit platformda bu 0xFFFFFFFF olur) gerçekleşir, ardından tekrar signed int'e dönüştürülür. Bu, uygulanabilirliğe bağlıdır, ancak çoğu zaman bu tekrar -1 (eğer iki's tamamlayıcısı kullanılıyorsa) olur. Ancak, doğru söylemek gerekirse: Sonuç, işaretli sayıların temsil standartlarına bağlıdır, ancak çoğu uygulamada sonuç -1 çıkacaktır.
Örnek:
int x = (int)(unsigned)-1; // x == -1 çoğu platformda
Hikaye
Dize işleyicisinde boyut karşılaştırma fonksiyonu kullanılmıştır: Eğer dize uzunluğu negatif olabiliyorsa, program hata bildiriyordu. Ancak, uzunluk size_t (unsigned) türündeydi ve
if(length < 0)kodu her zaman false döndürdüğü için bu sonsuz döngüye ve bellek taşmasına yol açmıştır.
Hikaye
Protokolün ayrıştırılması sırasında, ağ paketleri alanları unsigned olarak, yerel değişkenler ise signed olarak tutuluyordu. Bazı değerlerin işlenmesinde unsigned taşması nedeniyle paket uzunluğu hesaplamaları hatalı çıkmış ve bu durum bir tampon taşması zafiyetine yol açmıştır.
Hikaye
Günlüklerde tarih karşılaştırma modülü tarihi unsigned int olarak saklıyordu, ancak tarih aralığını int olarak arıyordu. Beklenen istisnanın tetiklenmesi yerine bazı sınır değerler kayıtların yanlış filtrelenmesine ve önemli günlüklerin kaybolmasına yol açtı.