Neden sıfır istisna ile bölme yapmadığımı tam olarak anlamıyorum:
int d = 0;
d /= d;
Bunun yerine sıfır istisna ile bir bölme almayı bekliyordum d == 1
.
Neden d /= d
sıfır istisna ile bölme atmıyor d == 0
?
Neden sıfır istisna ile bölme yapmadığımı tam olarak anlamıyorum:
int d = 0;
d /= d;
Bunun yerine sıfır istisna ile bir bölme almayı bekliyordum d == 1
.
Neden d /= d
sıfır istisna ile bölme atmıyor d == 0
?
throw
ifade tarafından atılır . Başka bir şey yok (tanımlanmamış davranış ülkesinde değilseniz).
Yanıtlar:
C ++ 'da yakalanacak bir "Sıfıra Göre Bölme" İstisnası yoktur. Gözlemlediğiniz davranış, Derleyici optimizasyonlarının sonucudur:
d == 0
) Tanımsız Davranış koşullarının gerçekleşmemesi gerektiğini çıkarır.d / d
her zaman 1'e eşit olmalıdır.Derleyiciyi kodunuzda küçük bir değişiklik yaparak sıfıra "gerçek" bir bölümü tetiklemeye zorlayabiliriz.
volatile int d = 0;
d /= d; //What happens?
Öyleyse şimdi soru kalıyor: derleyiciyi temelde bunun olmasına izin vermeye zorladığımıza göre, ne olacak? Bu tanımlanmamış bir davranıştır - ancak şimdi derleyicinin bu tanımsız davranış etrafında optimizasyon yapmasını engelledik.
Çoğunlukla hedef ortama bağlıdır. Bu yazılım istisna tetiklemez ama olabilir bir Donanım İstisna tetikleyebilir (hedef CPU bağlı olarak) (Tamsayı-Böl-by-Zero) bir yazılım durum yakalandı edilebilir geleneksel tarzda yakalanmış olamaz. Bu kesinlikle bir x86 CPU ve diğer (ama hepsi değil!) Mimariler için geçerlidir.
Bununla birlikte, sadece programın çökmesine izin vermek yerine donanım istisnasıyla başa çıkmanın yöntemleri vardır (eğer meydana gelirse): uygulanabilir olabilecek bazı yöntemler için bu gönderiye bakın : İstisnayı yakalama: sıfıra böl . Derleyiciden derleyiciye değiştiklerini unutmayın.
1
tamamen geçerli bir şeydir. 14684554'ü elde etmek, derleyicinin daha da optimize ettiği için olmalıdır - başlangıç d==0
koşulunu yayar ve bu nedenle yalnızca "bu 1 veya UB'dir" değil, aslında "bu UB, nokta" sonucuna varabilir. Bu nedenle sabiti yükleyen kod üretme zahmetine bile girmez 1
.
Sırf diğer cevapları tamamlamak için, sıfıra bölmenin tanımsız bir davranış olduğu gerçeği , derleyicinin, olacağı durumlarda her şeyi yapmakta özgür olduğu anlamına gelir :
0 / 0 == 1
ve buna göre optimize edebilir . Burada yaptığı etkili bir şekilde bu.0 / 0 == 42
ve d
bu değere ayarlayabilir .d
belirsiz olduğuna karar verebilir ve böylece değişkeni başlatılmamış olarak bırakabilir, böylece değeri, kendisi için ayrılmış belleğe önceden yazılan her şey olur. Yorumlarda diğer derleyicilerde gözlemlenen beklenmedik değerlerden bazıları, bu derleyicilerin böyle bir şey yapmasından kaynaklanıyor olabilir.d
derleme zamanında bilinmese bile , derleyici yine de hiçbir zaman sıfır olmadığını varsayabilir ve kodu buna göre optimize edebilir. OP'ın kodunun özel durumda, bu sadece varsayarak derleyici etkin bir farksızdır 0 / 0 == 1
, ama derleyici de, örneğin, varsayalım olabilir puts()
de if (d == 0) puts("About to divide by zero!"); d /= d;
asla çalıştırılmaktadır!Tamsayı sıfıra bölme davranışı C ++ standardı tarafından tanımlanmamıştır. O edilir değil bir özel durum için gerekli.
(Kayan noktayı sıfıra bölme de tanımsızdır, ancak IEEE754 bunu tanımlar.)
Derleyiciniz için optimize d /= d
ediyor, d = 1
bu da makul bir seçimdir. Kodunuzda tanımsız bir davranış olmadığını varsaymasına izin verildiğinden bu optimizasyonu yapmaya izin verilir - bu d
muhtemelen sıfır olamaz.
d
muhtemelen sıfır olamaz " olduğunu varsaymasının makul olduğunu söylediğinizde, derleyicinin şu satırı görmediğini de varsayıyor musunuz: int d = 0;
?? :)
Kodunuzun bu (ve diğer durumlarda) artırma güvenli sayısalları kullanarak bir C ++ istisnası oluşturmasını sağlayabileceğinizi unutmayın. https://github.com/boostorg/safe_numerics