[Kayıt için, bu cevabı kabul edildi ve oylandığından beri oldukça önemli bir şekilde düzenledim. Yine de temelde aynı şeyleri söylüyor.]
Bu kod derinden, belki de kasten kafa karıştırıcıdır. Dread undefined davranışının dar şekilde engellenmiş bir örneğini içerir . Bu soruyu oluşturan kişinin çok, çok zeki ya da çok, çok aptal olup olmadığını belirlemek temel olarak imkansızdır. Ve "ders", bu kodun size öğretmeyi ya da test etmeyi iddia edebilir - yani, tekli artı operatörün fazla bir şey yapmaması - kesinlikle bu tür yıkıcı yanlış yönlendirmeyi hak edecek kadar önemli bir kod değildir.
Kodun iki kafa karıştırıcı yönü vardır, garip durum:
while(+(+k--)!=0)
ve kontrol ettiği demans beyanı:
k=k++;
Önce ikinci kısmı ele alacağım.
Böyle bir değişkeni k1 arttırmak istiyorsanız, C size bir değil, iki değil, üç değil, bunu yapmak için dört farklı yol sunar:
k = k + 1
k += 1
++k
k++
Bu cömertliğe (veya belki de onun yüzünden) rağmen, bazı programcılar kafanız karışır ve
k = k++;
Bunun ne yapması gerektiğini anlayamıyorsanız, endişelenmeyin: kimse yapamaz. Bu ifade, kdeğerini ( k =parça ve k++parça) değiştirmek için iki farklı deneme içerir ve C'de yapılan değişikliklerin hangisinin kazanacağını söyleyen bir kural olmadığından, böyle bir ifade resmen tanımlanmamıştır , yani sadece o gelmiştir hiçbir anlamı tanımlanmış, ancak tüm program şüpheli olduğunu içeren söyledi.
Şimdi, çok dikkatli bakarsanız , bu belirli programda, hattın k = k++gerçekten yürütülmediğini göreceksiniz, çünkü (görmek üzere olduğumuz gibi) kontrol koşulu başlangıçta yanlıştır, bu nedenle döngü 0 kez çalışır . Bu nedenle bu özel program aslında tanımlanmamış olabilir - ancak yine de patolojik olarak kafa karıştırıcıdır.
Ayrıca , bu tür Tanımsız Davranışlarla ilgili tüm sorulara verilen bu standart SO yanıtlarına da bakın .
Ama k=k++parçayı sormadın . İlk kafa karıştırıcı kısmı, +(+k--)!=0durumu sordunuz . Çünkü bu, garip görünüyor olduğunu garip. Hiç kimse, böyle bir kodu gerçek bir programa yazmaz. Dolayısıyla, onu nasıl anlayacağınızı öğrenmek için hiçbir neden yok. (Evet, bu doğru, bir sistemin sınırlarını keşfetmek, onun ince noktaları hakkında bilgi edinmenize yardımcı olabilir, ancak kitabımda, hayali, küfürlü keşiflere karşı yaratıcı, düşündürücü keşifler arasında oldukça açık bir çizgi var ve bu ifade çok açık. bu satırın yanlış tarafı.)
Her neyse, inceleyelim +(+k--)!=0. (Ve bunu yaptıktan sonra, her şeyi unutalım.) Bunun gibi herhangi bir ifade içten dışa doğru anlaşılmalıdır. Sanırım ne olduğunu biliyorsun
k--
yapar. kGeçerli değerini alır ve ifadenin geri kalanına "döndürür" ve az çok eşzamanlı olarak azalır k, yani miktarı k-1tekrar depolar k.
Ama sonra ne yapar +? Bu tek artı, ikili artı değil. Tıpkı sıradan eksi gibi. İkili eksi çıkarma yaparsınız: ifade
a - b
b'yi a'dan çıkarır. Ve biliyorsunuz, tekli eksi bir şeyleri reddediyor: ifade
-a
size bir olumsuzluk verir. Tekin ne +yaptığı ... temelde hiçbir şey. pozitif değerleri pozitif ve negatif değerleri negatif olarak değiştirdikten sonra +asize adeğer verir . Yani ifade
+k--
sana ne verirse verir k--, yani keski değerdir.
Ama işimiz bitmedi, çünkü biz
+(+k--)
Bu sadece +k--size ne +verirse onu alır ve ona yine tek başına uygulanır . Size senkronizasyon Yani ne olursa olsun +k--ne olursa olsun, hangi size verdiği k--hangi kadar verdi, k'nin eski değer.
Sonuçta durum
while(+(+k--)!=0)
çok daha sıradan durumla aynı şeyi yapar
while(k-- != 0)
yapılmalıydı. (Aynı zamanda daha karmaşık görünen durumun while(+(+(+(+k--)))!=0)yapacağı şeyle aynı şeyi yapar . Ve bu parantezler gerçekten gerekli değildir; aynı şey while(+ + + +k--!=0)yaptıklarını da yapar .)
Hatta "normal" durumun ne olduğunu bulmak
while(k-- != 0)
biraz zor. Bu döngüde iki tür şey oluyor: Döngü potansiyel olarak birden çok kez çalıştığından, şunları yapacağız:
- daha küçük ve daha küçük
k--yapmak için yapmaya devam et k, aynı zamanda
- ne yaparsa yap, döngü gövdesini yapmaya devam et.
Ancak k--parçayı, döngüden başka bir yolculuk yapıp yapmayacağınıza karar vermeden önce (veya süreçte) hemen yaparız . Ve unutmayın ki , azaltmadan önce k--eski değerini "döndürür" k. Bu programda, başlangıç değeri k0'dır. Bu nedenle k--, eski 0 değerini "döndürür", ardından k-1 olarak güncellenir . Ama sonra durumun geri kalanı != 0- ama gördüğümüz gibi, durumu ilk kez test ettiğimizde, 0 aldık. Bu yüzden döngüden herhangi bir yolculuk yapmayacağız, bu yüzden sorunlu bir ifade k=k++.
Başka bir deyişle, bu özel döngüde, "devam eden iki şey var" dememe rağmen, 1 şeyin bir kez gerçekleştiği, ancak 2 şeyin sıfır kez gerçekleştiği ortaya çıkıyor.
Her halükarda, umarım bir program için bu kötü bahanenin neden nihai değer olarak -1 baskısı ile sonuçlandığı yeterince açıktır k. Normalde, böyle sınav sorularına cevap vermek istemiyorum - hile gibi geliyor - ama bu durumda, egzersizin tüm noktasına çok titiz bir şekilde katılmıyorum, aldırmıyorum.