Bu UB; ISO C ++ terimlerinde, tüm programın tüm davranışı, sonunda UB'ye çarpan bir yürütme için tamamen belirtilmez . Klasik örnek, C ++ standardının umduğu kadarıyla, şeytanların burnunuzdan uçmasını sağlayabilir. (Nazal iblislerin gerçek bir olasılık olduğu bir uygulamaya karşı öneriyorum). Daha fazla ayrıntı için diğer yanıtlara bakın.
Derleyiciler derleme zamanında görülebilen UB'ye yol açan görebileceği yürütme yolları için derleme zamanında "soruna neden olabilir", örneğin bu temel bloklara asla ulaşılmadığını varsayın.
Ayrıca bkz. Her C Programcısının Tanımsız Davranış Hakkında Bilmesi Gerekenler (LLVM blogu). Burada açıklandığı gibi, imzalı taşma UB, derleyicilerin for(... i <= n ...), bilinmeyenler için bile, döngülerin sonsuz döngüler olmadığını kanıtlamasını sağlar n. Ayrıca int döngü sayaçlarını işaret uzantısını yeniden yapmak yerine işaretçi genişliğine "yükseltmelerine" olanak tanır. (Dolayısıyla, bu durumda UB'nin sonucu, bir dizinin düşük 64k veya 4G öğelerinin dışına erişiyor olabilir,i değer aralığına .)
Bazı durumlarda derleyiciler, ud2yürütüldüğünde UB'ye neden olabilecek bir blok için x86 gibi yasadışı bir talimat yayınlarlar . (Bir işlev olabilir Not o değil derleyiciler değil genel go Berserk ve UB vurma bir fonksiyonu sayesinde diğer işlevleri, hatta mümkünse yolları kırabilir hiç çağrılabilir, böylece. Yani makine kodu ne için zorunluluk hala işe derler UB'ye yönlendirmeyen tüm girişler.)
Muhtemelen en verimli çözüm, gereksiz olanlardan factor*=10kaçınılması için son yinelemeyi manuel olarak soymaktır.
int result = 0;
int factor = 1;
for (... i < n-1) { // stop 1 iteration early
result = ...
factor *= 10;
}
result = ... // another copy of the loop body, using the last factor
// factor *= 10; // and optimize away this dead operation.
return result;
Veya döngü gövdesi büyükse, yalnızca işaretsiz bir tür kullanmayı düşünün factor. Daha sonra imzasızın taşmasına izin verebilirsiniz ve sadece 2 gücüne (imzasız türdeki değer bitlerinin sayısı) iyi tanımlanmış bir sarma yapar.
Bu Kullanmaya bile gayet ile sizin unsigned-> imzalı dönüşüm taşıyor asla, özellikle imzalı türleri.
İmzasız ve imzalanmış tamamlayıcı arasındaki dönüşüm ücretsizdir (tüm değerler için aynı bit örüntüsü); C ++ standardı tarafından belirtilen int -> unsigned için modulo kaydırma, tamamlayıcı veya işaret / büyüklüğünün aksine, sadece aynı bit desenini kullanmayı kolaylaştırır.
Ve imzasız-> imzalı benzer şekilde önemsizdir, ancak daha büyük değerler için uygulama tanımlıdır INT_MAX. Eğer değilseniz kullanarak son yineleme gelen büyük işaretsiz bir sonuç, endişelenecek bir şey yok. Ancak öyleyse bkz . İmzasızdan imzalıya dönüşüm tanımsız mı? . Value-fit-case durumu, uygulama tanımlıdır ; bu, bir uygulamanın bir miktar davranış seçmesi gerektiği anlamına gelir ; aklı başında olanlar sadece imzasız bit desenini keser (gerekirse) ve imzalı olarak kullanırlar, çünkü bu aralık içi değerler için ekstra çalışma olmadan aynı şekilde çalışır. Ve kesinlikle UB değil. Böylece büyük işaretsiz değerler negatif işaretli tamsayılar haline gelebilir. örneğin gcc ve clang'dan sonra int x = u; optimizasyon yokx>=0-fwrapvdavranışı tanımladıkları için, onlar olmadan da her zaman doğrudurlar .