Değerlendirme ihlallerinin sırası hakkında okuyordum ve beni şaşırtan bir örnek veriyorlar.
1) Bir skaler nesne üzerindeki bir yan etki, aynı skaler nesne üzerindeki başka bir yan etkiye göre sıralı değilse, davranış tanımsızdır.
// snip f(i = -1, i = -1); // undefined behavior
Bu bağlamda, i
a, skaler bir amacı , görünüşte araçlar
Aritmetik türler (3.9.1), numaralandırma türleri, işaretçi türleri, işaretçi-üye türleri (3.9.2), std :: nullptr_t ve bu türlerin (3.9.3) cv nitelikli sürümleri topluca skaler tipler olarak adlandırılır.
Bu durumda ifadenin nasıl belirsiz olduğunu anlamıyorum. Bana öyle geliyor ki, ilk ya da ikinci argüman ilk değerlendirilirse, i
sonlanır -1
ve her iki argüman da değerlendirilir -1
.
Birisi lütfen açıklığa kavuşturabilir mi?
GÜNCELLEME
Tüm tartışmaları gerçekten takdir ediyorum. Şimdiye kadar, @ harmic'in cevabını çok seviyorum, çünkü ilk bakışta ne kadar ileri göründüğüne rağmen bu ifadeyi tanımlamanın güçlüklerini ve karmaşıklıklarını ortaya koyuyor. @ acheong87 referansları kullanırken ortaya çıkan bazı sorunlara dikkat çekiyor, ancak bu sorunun sorulmamış yan etkiler yönüne dik olduğunu düşünüyorum.
ÖZET
Bu soru çok dikkat çektiğinden, ana noktaları / cevapları özetleyeceğim. İlk olarak, "neden" yakından "ne yani henüz ustaca farklı anlamlar ilgili olabileceği anlamına işaret etmek bana küçük anlatılanlar izin sebebi " ne, " nedeni " ne "ve amaç ". Yanıtları, "neden" olarak adlandırdıkları bu anlamlardan hangileriyle gruplandıracağım.
hangi sebepten dolayı
Buradaki ana cevap, Paul Draper'dan geliyor , Martin J de benzer ama kapsamlı olmayan bir cevaba katkıda bulunuyor. Paul Draper'ın yanıtı
Tanımlanmamış bir davranıştır, çünkü davranışın ne olduğu tanımlanmamıştır.
Cevap, C ++ standardının söylediklerini açıklamak açısından genel olarak çok iyi. Ayrıca, f(++i, ++i);
ve gibi bazı UB vakalarını da ele alır f(i=1, i=-1);
. İlk bağımsız değişken olmalıdır, alakalı durumlarda ilk olarak, açık değil i+1
, ikinci i+2
ya da tam tersi; ikincisinde, i
işlev çağrısından sonra 1 veya -1 olması gerektiği açık değildir . Bu iki durum da UB'dir, çünkü aşağıdaki kurallara girerler:
Bir skaler nesne üzerindeki bir yan etki, aynı skaler nesne üzerindeki başka bir yan etkiye göre sıralanmamışsa, davranış tanımsızdır.
Bu nedenle, f(i=-1, i=-1)
programcının amacı (IMHO) açık ve açık olmasına rağmen, aynı kuralın altına düştüğü için de UB'dir.
Paul Draper ayrıca,
Tanımlanmış bir davranış olabilir mi? Evet. Tanımlandı mı? Hayır.
bu da bizi "hangi nedenle / amaç için f(i=-1, i=-1)
tanımsız davranış olarak kaldı?"
hangi nedenle / amaç için
C ++ standardında bazı gözetim (belki de dikkatsiz) olmasına rağmen, birçok ihmal iyi gerekçelendirilmiştir ve belirli bir amaca hizmet eder. Her ne kadar amacın ya "derleyici yazarın işini kolaylaştırmak" ya da "daha hızlı kod" olduğunu bilsem de, temelde UB olarak iyi bir neden olup olmadığını bilmekle ilgileniyordum f(i=-1, i=-1)
.
Zararlı ve supercat , UB için bir neden sağlayan ana cevapları sağlar . Harmic, görünüşte atomik atama işlemlerini birden fazla makine talimatına ayırabilecek bir optimize edici derleyicinin ve optimum hız için bu talimatları daha fazla araya sokabileceğine dikkat çekiyor. Bu çok şaşırtıcı sonuçlara yol açabilir: i
senaryosunda -2 olur! Bu nedenle, zararlı, aynı değerin bir değişkene birden çok kez atanmasının, işlemlerden etkilenmezse nasıl kötü etkileri olabileceğini gösterir.
supercat, f(i=-1, i=-1)
olması gerektiği gibi görünmeye çalışmanın tuzaklarının ilgili bir açıklamasını sağlar . Bazı mimarilerde, aynı bellek adresine birden fazla eşzamanlı yazma işlemine karşı katı kısıtlamalar olduğuna dikkat çekiyor. Bir derleyici, daha az önemsiz bir şeyle uğraşırsak bunu yakalamakta zorlanabilir f(i=-1, i=-1)
.
davidf ayrıca zarar verenlere çok benzeyen serpiştirme talimatlarının bir örneğini sunar.
Zararlıların, süper kedilerin ve davidflerin örneklerinin her biri biraz tartışmalı olsa da, birlikte ele alındıklarında neden f(i=-1, i=-1)
tanımsız davranışlar olması gerektiğine dair somut bir neden sunmaya devam ediyorlar .
Zararlıların cevabını kabul ettim, çünkü Paul Draper'ın cevabı "hangi sebepten ötürü" kısmına daha iyi hitap etmesine rağmen, nedenin tüm anlamlarını ele almak için en iyi işi yaptı.
diğer cevaplar
JohnB , aşırı yüklenmiş atama işleçlerini (yalnızca düz skalalar yerine) düşünürsek, o zaman da başımız belaya girebilir.
f(i-1, i = -1)
veya benzeri bir şey anlamına geliyordu .
std::nullptr_t
, ve bu türlerin (3.9.3) cv nitelikli sürümleri topluca skaler tipler olarak adlandırılır . "