C geliştiricilerini “i ++ == ++ i” ise meraklı yapan nedir? [kapalı]


15

Sadece rastgele bir gözlem, StackOverflow.com üzerinde "++ i == i ++" hakkında sorular var gibi görünüyor. Bu soru her zaman soruluyor, sanırım son 2 ay içinde 6 veya 7 kez sorduğunu gördüm.

C geliştiricilerinin neden bu kadar ilgilendiğini merak ediyorum. Aynı kavram / soru C # ve Java devs için de var, ama sanırım sadece bir C # ile ilgili soru gördüm.

Birçok örnek ++ i kullandığından mı? Bazı popüler kitap veya öğretici olduğu için mi? Çünkü C geliştiricileri sadece 'verimlilik' / 'performans' için tek bir çizgide olabildiğince sıkıştırmayı seviyorlar ve bu nedenle ++ operatörünü kullanarak 'garip' yapılarla karşılaşıyorlar mı?


23
(Benim için bir C # dev, i ++ ve ++ i eşittir. Ben bilmiyorum, ama farklılığa bağlı bir kod yazarsam, ben daha okunabilir olmak ve derleyici ve JITter ilgilenmesini bekliyoruz refactor istiyorsunuz ancak, bir C # dev olarak zaten bir veya iki saat döngüsünü kaydetmeye çalışmıyorum çünkü zaten zaten zaten verimsizim)
Michael Stum

1
tomurcuklanan programcılar olarak aritmetik, mantıkla oynamayı seviyoruz ve işlerin nasıl çalıştığını merak ediyoruz. Bence bu tür soruları sevmemiz için büyük bir sebep var. çığır açıcı bir özellik olmayabilir ama ilginç! ilk etapta programcı olmamızın nedeni bu değil mi?!
Chani

2
Kelimenin tam anlamıyla ifadeye mi ++i == i++, daha genel olarak ++ive arasındaki anlam farkına mı atıfta bulunuyorsunuz i++?
Keith Thompson

Yanıtlar:


30

En azından bir kısmının biraz daha basit olduğundan şüpheleniyorum: şimdi bile, okul yılının başlangıcında başlayan böyle birçok soru görüyoruz ve yıl boyunca yavaş yavaş azalıyorlar.

Bu nedenle, bence çok azının öğretmenin en azından biraz konuştuğu, ancak puanlarını çok iyi açıklamadığı (çoğu zaman) çünkü onları gerçekten anlamıyor). Özellikle bu soruları soran insanlara dayanarak, çok azı gerçek kodlamaya dayanmaktadır.


14
Bu Ebedi Eylül'ün tam tersi değil mi? Ebedi eylül , AOL'nin Usenet'e müşterilerine erişim sunmaya başladığı Eylül ayıydı (okula başlayan yeni öğrencilerin geleneksel olarak panoları yeni başlayanlar olarak bombaladığı ay).
nlawalker

Bu ilginç bir teoridir, ancak birileri materyali anlamadıysa her zaman öğretmenlerin hatası değildir: belki de öğrenciler (1) sınıf sırasında yeterince dikkat etmiyorlardı ve (2) daha önce yığın akışı hakkında bir cevap aramak için çok tembellerdi aynı soruyu tekrar soruyorum.
Giorgio

12

Çünkü C programcıları işlem sırasını anlamalıdır. C # geliştiricileri normalde diğer şeyler hakkında daha fazla endişelendiğimiz için bitsel işleçleri (&, |, ~) veya önek işleçlerini kullanmazlar. Bununla birlikte, C # devs'in farkına varmadığımız şey, günlük olarak kullandığımız operatörlerin ne yaptığını ve bunları nasıl doğru kullanacağımızı bilmemiz gerektiğidir. Çoğumuz bunun bir sorun olabileceği yerlerden kaçınırız.

Başınızın üstünde, bu parçacığın çıktısı nedir?

    double x = 5.5;
    Console.WriteLine(x++);
    x = 5.5;
    Console.WriteLine(++x);

Tecrübeli C # devs Konsol çıktı ne olduğu hakkında hiçbir fikrim yok söyleyebilirim.


3
+1. Düzeltme öncesi ve sonrası artış / azaltma operatörleri arasındaki farkı bilmek, bu gibi durumlar için buna değer.
Maulrus

4
Ben tür görmek ve ben de çıktı bilmiyordum (5.5 ve 6.5 olduğuna inanıyorum, ama emin değilim), ve benim için ben x ++ için refactor olur gibi önemli olmaz; Console.WriteLine (x); hemen. Ben tamamen cahil değilim, sadece sıfır kullanılabilirlik ile büyük bir kod kokusu olduğunu düşünüyorum.
Michael Stum

9
Sorunun cevabının işlem sırası veya önek ve düzeltme sonrası artışları arasındaki farkla ilgisi yoktur. Bu, tanımlanmış ve tanımlanmamış bir davranış meselesidir.
David Thornley

2
Bugün bunu gördüm. Gibi bir şey if (myList[i++] == item). Zeki. Bir IndexOutOfRange istisna kaynağı arıyor buldum ... Gerçekten, çok "zeki".
rmac

7
Sanırım 5.5 ve 6.5, ama daha ++önce bir şamandıra üzerinde kullanıldığını hiç görmedim ve çok uygun hissetmediğini söylemeliyim. İnsanlar bunu yapıyor mu? (Tercih ederim += 1)
Bart van Heukelom

8

Bence bu çok açık. C # 'da, bir int i, i++ == ++iher zaman yanlış olsa ++i == i++da her zaman doğrudur, güvenilirdir ve ilgilenen herkes bunu sadece C # kurallarını öğrenerek (veya sadece çalıştırarak) kolayca bulabilir.

C ve C ++ 'da ise, derleyiciye, yürütme ortamına, platforma vs. bağlı olduğu için tanımlanmamıştır, bu yüzden cevaplamak çok daha zor bir soru, bu yüzden birçok insan bunu soruyor.


+1 - ancak cevaplaması gerçekten zor bir soru değil. "tanımsız" bir kelimedir. Tüm "buna bağlı ..." şeyler çoğu insanın endişe etmediği şeyler. Sadece belirli bir platform için yazıyor olsanız bile, dil için bir bütün olarak normal deyimleri kullanmalısınız ve artım öncesi ve arttırma sonrası operatörlerinin çoğu kullanımı birkaç yaygın deyimin bir parçasıdır.
Steve314

+1: Bu aslında sorulan soruyu cevaplar (yani satırlar arasında okumuyorsunuz).
Thomas Eding

7

Bu popüler bir soru çünkü hileli bir soru. Tanımsız .

Yukarıdaki bağlantı, Bjarnes Stroustrup'un ana sayfasında, bu soruyu özellikle ele alan ve bu yapının neden tanımlanmadığını açıklayan bir SSS'ye gidiyor. Ne diyor:

Temel olarak, C ve C ++ 'da, bir değişkeni de yazdığınız bir ifadede iki kez okursanız, sonuç tanımsız olur.

Değerlendirme sırasının tanımlanmamış olması, daha iyi performans gösteren kod verdikleri iddia edilir.


5

Büyük olasılıkla, C'de, yazma i++veya ++iişaretçi aritmetiği yaparken gerçekten önemlidir . Orada, ibir ameliyattan önce veya sonra artan önemli olabilir. Size bir örnek verirdim ama en son C yazdığım zaman 10 yıl önceydi ...

C # 'da asla düşünmem gereken bir durumla karşılaşmadım i++ya da ++iAFAIK, for / while döngüleri için gerçekten önemli değil.


3
C # 'daki farkları anlamak hala önemlidir - sadece onları / döngüler için kullandığınız için onları bulacağınız tek yer bu değildir
STW

tamamen doğru.
Mladen Prajdic

3
Bu soru ile ilgili değil. Soru, i++ve arasındaki farkla ilgili değil ++i, aynı ifadede birleştirmektir.
David Thornley

@David Soru, C programcılarının neden merak ettikleri. Cevap (C'de önemli, C #'da çok fazla değil) tamamen ilgili ".
Florian F

2

Birkaç yıl önce, bu operatörlerin tehlikeli kabul edildiğini okudum, bu yüzden daha fazla bilgi kazmaya çalıştım. Stackoverflow o zamanlar yukarı olsaydı, orada sordum.

Çünkü bazı bükülmüş insanlar

while( [something] )
{
  a[++j] = ++j;
}

Şimdi bile, ne olacağı / ne olacağı konusunda çok emin değilim, ama aynı satırdaki birden fazla ++ [var] 'ın sorun istediğini açıkça anladım.


2
Artışlar C
tzenes

7
Gibi atamalar x = ++j;C'de iyi tanımlanmıştır. Yukarıdaki tanımlanmamıştır, çünkü jaraya giren bir dizi noktası olmadan iki kez modifiye edilmiştir.
Matthew Flaschen

2

İki sebep.

++ i'nin doğru uygulanması, i'yi arttırmak ve sonra geri döndürmektir. İ ++ 'ın doğru uygulanması, geçerli değeri kaydetmek, i değerini artırmak ve kaydedilen değeri döndürmektir. Bunların eş anlamlı olarak uygulanmadığını bilmek önemlidir.

Daha sonra soru , derleyici eşitlik gibi bir ifadeyi değerlendirirken bunları ne zaman uygular.

Eşitlik testi önce yapılırsa, önce ve sonra artış operatörleri, önce sol taraf (lhs) ve sağ taraf (rhs) değerlendirilenden farklı bir mantık yazmanız gerekir, ardından eşitlik.

Her şey işlem sırası ile ilgilidir ve bu da kişinin yazdığı kodu etkiler. Ve şaşırtıcı bir şekilde, tüm diller aynı fikirde değil.

Temel testler listesi, geliştiricilerin varsayımlarının doğru olup olmadığını ve gerçek uygulamanın dil spesifikasyonuyla eşleşip eşleşmediğini test etmelerini sağlar.

Bu, işaretçilerle, döngülerle veya değerlerle dönerken her türlü etkiye sahip olabilir.


5
Bu konuda temel testler yanıltıcı olacaktır, çünkü tanımlanmamış davranıştır. Bu sefer beklediğiniz gibi çalışırsa, bir dahaki sefere olacağının garantisi yoktur.
David Thornley

Yanlış soruyu cevapladınız. C programcılarının neden merak ettiğini cevaplamalısınız.
Hugo

Ikinci para (en azından önceden C ++ 11) yanlış zaten olduğu: davranışı ++iolan değerini kullanıni+1 ve sonraki dizi noktasından önce, artım belki önce veya sonra, zaman içinde bir noktada, fakati .
AA

@MattMcNabb - Beni bunun için bir spesifikasyona yönlendirebilir misiniz, uygulamada bir şeylerin değişip değişmediğini öğrenmek isterim. C'nin PDP montajıyla güzel eşleştirildiği günlerde, ++ i bir INC talimatı enjekte ederken, sonek sürümü artıştan sonra bir talimat kullanmak için bir kayıttaki değeri kopyalamak zorunda kaldı. Tanımladığınız değişikliğin gerekliliğini ne oluşturdu?
Walt Stoneburner

2

Bence bu bir kültür şoku olayı.

Daha önce belirtildiği gibi, C veya C ++ 'da bir ifadenin davranışı tanımlanmamış olabilir, çünkü artım sonrası vb. İşlem sırası kesin olarak tanımlanmamıştır. Tanımsız davranış C'de oldukça yaygındır ve elbette bunların çoğu C ++ 'a aktarılmıştır.

Başka bir dilde programlama yapan birine - programlama dillerinin kesin olması gerektiği ve bilgisayarların kendilerine söyledikleri şeyi yapmaları gerektiği fikrini alan birisi ... C'nin bazı şeyler hakkında kasıtlı olarak belirsiz olduğunu keşfedin.


C bu şekilde, çünkü düşünebileceğiniz en garip gömülü veya anabilgisayar platformları da dahil olmak üzere C # tanımlandığında bile mevcut olandan çok daha fazla platformu desteklemek üzere tasarlandı. Öte yandan, C # ... x86 ve 360 ​​üzerinde çalışır? belki de ARM? Başka hiçbir şey. Bu yüzden C # çok daha fazlasını tanımlayabilir.
DeadMG

++ Ayrıca, C ilk olarak PDP-11 üzerine inşa edilmedi mi? Otomatik artış talimatları nerede vardı? C "sete yakın" olmak istedi, böylece talimat setini yararlı bir şekilde kullanabilirdi.
Mike Dunlavey

@MikeDunlavey: Hayır, C'ler ++ve --operatörler, bu operatörler C'nin önceki dili B'de tanıtıldığında mevcut olmayan PDP-11'e dayanmıyordu . Bkz. Cm.bell-labs.com/who/dmr/chist.html ve "otomatik artış" için arama yap.
Keith Thompson

1

Belki de sadece C geliştiricilerinin genel olarak ++ artışını kullanması - C'nin diziler arasında yineleme yapmak için nasıl "öngörü" ya da benzer bir ifadesi olmadığını görmek. Oh, ve tabii ki daha önce de belirtildiği gibi işaretçi aritmatik!


1
İyi bir nokta, foreach'in nispeten modern bir kavram olduğunu unuttum.
Michael Stum

-1

Her iki parça arasındaki fark: yazı ve ön baskı, bu iki kod parçasının her dilde çalışması gerektiği şekilde çalışıyor. BU DİL BAĞIMLI DEĞİL !!!

++i

Bu bir artıştır. Bu kod parçası i, değeri kullanıldığı satıra göndermeden önce değerini artıracaktır .

i++

Bu artım sonrasıdır. Bu kod parçası , kullanıldığı satırdaki ideğerini artırmadan önce değerini döndürür i.

Başka bir küçük örnekte:

int main(void)
{
  int i = 0; 
  int result; 
  result = 10 + ++i; 
  printf("%d \n", result); // = 11 

  int j = 0; 
  result = 10 + j++; 
  printf("%d \n", result);// = 10
  return 0;
}

Bu kod, kod takımındaki sonuçlarla derlenir.

Bu, operatör aşırı yüklemesinin dahili uygulamasıyla ilgilidir.

++i değeri doğrudan artırır (ve bu nedenle biraz daha hızlıdır)

i++ önce gerekli olan yere geri gönderilecek bir kopya oluşturur ve daha sonra i değişkenin arttırılır.

Umarım şimdi açıktır.


Ancak bu asıl soruyu ele almıyor: C geliştiricileri neden diğerlerinden daha fazla soruyorlar. OP operatörleri anlar.
Martijn Pieters

Ayrıca bu cevap aslında yanlıştır. ++idaha hızlı değildir ve i++bir kopya oluşturmaz. Ayrıca, ++idiğer diller arasında bırakılmaksızın, C ++ 'dan biraz farklı davranır.
MM
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.