Bir C ++ işlevinin belirli bir değişkenin değerini değiştirip değiştirmeyeceğini belirleyebilecek bir derleyici oluşturmak neden imkansızdır?


104

Bu satırı bir kitapta okudum:

Bir C ++ işlevinin belirli bir değişkenin değerini değiştirip değiştirmeyeceğini gerçekten belirleyebilecek bir derleyici oluşturmak imkansızdır.

Paragraf, derleyicinin sabitliği kontrol ederken neden muhafazakar olduğundan bahsediyordu.

Böyle bir derleyici oluşturmak neden imkansız?

Derleyici, bir değişkenin yeniden atanıp atanmadığını, üzerinde const olmayan bir işlevin çağrılıp çağrılmadığını veya const olmayan bir parametre olarak aktarılıp aktarılmadığını her zaman kontrol edebilir ...


24
Aklıma gelen ilk şey dinamik bağlantı kütüphaneleri. Makinemde kod derlersem ve siz makinenizde kod derlerseniz ve bunları çalışma zamanında bağlarsak, derleyiciniz değişkenleri değiştirip değiştirmediğimi nasıl anlayabilir?
Mooing Duck 01

4
@MooingDuck Tam olarak bu. Daha geniş bir ifadeyle, derleyici işlevi tek tek derlemez, ancak onu daha geniş bir resmin parçası olarak derler; bu, tümü derleyicinin kapsamı dahilinde olmayabilir.
2013

3
"imkansız" bir abartı olabilir - "hesaplama açısından olanaksız" (NP'de olduğu gibi) daha iyi bir karakterizasyon olabilir, ancak öğrenci için biraz daha zordur. Bağlantılı bir liste veya başka bir soyut veri yapısını hayal edin. Bu listedeki / ağaçtaki / her neyse, bir düğümü değiştiren bir işlevi çağırırsam, bir derleyici, programı temelde tam olarak simüle etmeden, hangi düğümün değiştirildiğini (ve belki daha da önemlisi, hangilerinin yapılmadığını) kanıtlamayı nasıl umabilir? bir kaynak dosyayı derlemek 3 gün
sürmemekle birlikte

36
@twalberg İmkansız bir abartma değildir, Halting sorunu burada birkaç yanıtın açıkladığı gibi geçerlidir. Genel bir programı algoritmik olarak tam olarak analiz etmek mümkün değildir.
Fiktik 13 Temmuz'da

5
@twalberg Yalnızca geçerli programların bir alt kümesini derleyen derleyiciler pek kullanışlı değildir.
Caleb

Yanıtlar:


139

Böyle bir derleyici oluşturmak neden imkansız?

Aynı nedenle, herhangi bir programın sonlanıp sonlanmayacağını belirleyecek bir program yazamazsınız. Bu, durma sorunu olarak bilinir ve hesaplanamayan şeylerden biridir.

Açık olmak gerekirse, bazı durumlarda bir işlevin değişkeni değiştirdiğini belirleyebilen bir derleyici yazabilirsiniz , ancak işlevin değişkeni değiştirip değiştirmeyeceğini (veya durdurmayacağını) güvenilir bir şekilde yazamazsınız. mümkün olan her işlev.

İşte kolay bir örnek:

void foo() {
    if (bar() == 0) this->a = 1;
}

Bir derleyici, sadece bu koda bakarak, bir daha değişip foodeğişmeyeceğini anasıl belirleyebilir? Yapıp yapmadığı, işlevin dışındaki koşullara, yani bar. Durdurma sorununun hesaplanabilir olmadığının kanıtı için bundan daha fazlası var, ancak bağlantılı Wikipedia makalesinde (ve her hesaplama teorisi ders kitabında) güzel bir şekilde açıklanmış, bu yüzden burada doğru bir şekilde açıklamaya çalışmayacağım.


48
@mrsoltys, kuantum bilgisayarlar bazı problemler için "sadece" katlanarak daha hızlıdırlar, çözülemeyen problemleri çözemezler.
zch

8
@mrsoltys Bu üssel olarak karmaşık algoritmalar (faktöring gibi) kuantum bilgisayarlar için mükemmeldir, ancak durdurma problemi mantıksal bir ikilemdir, ne tür bir "bilgisayara" sahip olursanız olun hesaplanamaz.
user1032613

7
@mrsoltys, akıllıca olmak için, evet, bu değişirdi. Ne yazık ki, bu, algoritmanın hem sonlandırıldığı hem de çalıştığı anlamına gelir, maalesef, hangisinin gerçek durumu etkilediğini doğrudan gözlemlemeden hangisi olduğunu anlayamazsınız.
Nathan Ernst

9
@ ThorbjørnRavnAndersen: Tamam, farz edin ki bir programı çalıştırıyorum. Sonlandırılıp sonlanmayacağına tam olarak nasıl karar vereceğim?
ruakh

8
@ ThorbjørnRavnAndersen Ancak programı gerçekten çalıştırırsanız ve program sonlanmazsa (örneğin sonsuz bir döngü), onun bitmediğini asla öğrenemezsiniz ... sadece bir adım daha yürütmeye devam edin, çünkü olabilir sonuncusu ...
MaxAxeHax

124

Böyle bir derleyicinin var olduğunu hayal edin. Ayrıca, kolaylık sağlamak için, iletilen işlev verilen bir değişkeni değiştirirse 1 ve işlev değiştirmediğinde 0 döndüren bir kitaplık işlevi sağladığını varsayalım. O halde bu program ne yazdırmalı?

int variable = 0;

void f() {
    if (modifies_variable(f, variable)) {
        /* do nothing */
    } else {
        /* modify variable */
        variable = 1;
    }
}

int main(int argc, char **argv) {
    if (modifies_variable(f, variable)) {
        printf("Modifies variable\n");
    } else {
        printf("Does not modify variable\n");
    }

    return 0;
}

12
Güzel! Yalancı paradoksu duyuyorum bir programcı tarafından yazılmış olarak.
Krumelur

28
Aslında bu, durdurma sorununun karar verilemezliğine dair meşhur kanıtın güzel bir uyarlaması .
Konstantin Weitz

10
Bu somut durumda, "modifications_variable" doğru döndürmelidir: Değişkenin gerçekten değiştirildiği en az bir yürütme yolu vardır. Ve bu yürütme yoluna, deterministik olmayan harici bir fonksiyona yapılan bir çağrıdan sonra ulaşılır - bu nedenle tüm fonksiyon deterministik değildir. Bu 2 nedenden dolayı, derleyici pesimistik görünümü almalı ve değişkeni değiştirdiğine karar vermelidir. Değişkeni değiştirmenin yoluna deterministik bir karşılaştırmadan sonra ulaşılırsa (derleyici tarafından doğrulanabilir) yanlış (yani "1 == 1") verirse, derleyici güvenli bir şekilde böyle bir işlevin değişkeni asla değiştirmediğini söyleyebilir
Joe Pineda

6
@JoePineda: Soru fdeğişkeni değiştirip değiştiremeyeceğidir - değişkeni değiştirip değiştiremeyeceği değil. Bu cevap doğrudur.
Neil G

4
@JoePineda: hiçbir şey, kodunu modifies_variablederleyici kaynağından kopyalamamı / yapıştırmamı engellemiyor , argümanınızı tamamen geçersiz kılıyor. (açık kaynak olduğu varsayılarak, ancak konu açık olmalıdır)
orlp

60

Şaşırtmak etmeyin "veya bu girdileri verilen bir değişken değiştirmez olacak" için "bir değişken değiştiren bir yürütme yolu vardır."

İlki opak yüklem belirleme olarak adlandırılır ve karar vermek önemsiz bir şekilde imkansızdır - durdurma sorununun azaltılmasının yanı sıra, girdilerin bilinmeyen bir kaynaktan (örn. Kullanıcı) gelebileceğini belirtebilirsiniz. Bu sadece C ++ değil tüm diller için geçerlidir .

İkinci açıklama ise edebilir tüm optimize derleyiciler yapmak bir şey olduğunu ayrıştırma ağaca bakarak belirlenebilir. Yaptıkları sebebi olmasıdır saf fonksiyonlar (ve referentially şeffaf için fonksiyonlar, referentially şeffaf bazı tanım ) derleme sırasında belirlenen kolayca inlinable olmak ya değerlerini olması gibi, uygulanabilir güzel optimizasyonlar her türlü var; ancak bir fonksiyonun saf olup olmadığını bilmek için , bir değişkeni değiştirip değiştiremeyeceğini bilmemiz gerekir .

Dolayısıyla, C ++ ile ilgili şaşırtıcı bir ifade gibi görünen şey aslında tüm diller hakkında önemsiz bir ifadedir.


5
Bu en iyi cevap, bu ayrımı yapmak önemli.
UncleZeiv

"önemsiz derecede imkansız" mı?
Kip

2
@Kip "karar vermek önemsiz şekilde imkansız" muhtemelen "karar vermek imkansız ve kanıt önemsiz" anlamına gelir.
fredoverflow

28

"Bir C ++ fonksiyonunun belirli bir değişkenin değerini değiştirip değiştirmeyeceğindeki" anahtar kelime "will" dir. Bir C ++ işlevinin belirli bir değişkenin değerini değiştirmesine izin verilip verilmediğini kontrol eden bir derleyici oluşturmak kesinlikle mümkündür , değişikliğin gerçekleşeceğini kesin olarak söyleyemezsiniz:

void maybe(int& val) {
    cout << "Should I change value? [Y/N] >";
    string reply;
    cin >> reply;
    if (reply == "Y") {
        val = 42;
    }
}

"Bir C ++ işlevinin belirli bir değişkenin değerini değiştirip değiştiremeyeceğini kontrol eden bir derleyici oluşturmak kesinlikle mümkündür" Hayır, değil. Caleb'in cevabına bakın. Bir derleyicinin foo () 'nun a'yı değiştirip değiştiremeyeceğini bilmesi için, bar ()' ın 0 döndürmesinin mümkün olup olmadığını bilmesi gerekir. Ve herhangi bir hesaplanabilir işlevin tüm olası dönüş değerlerini söyleyebilen hesaplanabilir bir işlev yoktur. Dolayısıyla, derleyicinin onlara ulaşılıp ulaşılamayacağını söyleyemeyeceği kod yolları vardır. Bir değişken yalnızca ulaşılamayan bir kod yolunda değiştirilirse değişmez, ancak bir derleyici onu algılamaz
Martin Epsz

12
@MartinEpsz "Can" derken "değişmesine izin veriliyor", "değiştirilemez" değil. const-Ness kontrollerinden bahsederken OP'nin aklında olan şeyin bu olduğuna inanıyorum.
dasblinkenlight

@dasblinkenlight OP'nin ilkini kastettiğine, "değişmesine izin verildiğine" veya "değişebilir veya değişmeyeceğine" karşı "kesinlikle değişmeyecek" olduğuna inandığımı kabul etmeliyim. Elbette bunun bir sorun olacağı bir senaryo düşünemiyorum. Hatta derleyiciyi, tanımlayıcı veya "değişebilir" yanıt niteliğine sahip bir işleve çağrı içeren herhangi bir işlevde "değişebilir" yanıtını verecek şekilde bile değiştirebilirsiniz. Bununla birlikte, C ve C ++, şeylerin çok gevşek bir tanımına sahip oldukları için bunu denemek için korkunç dillerdir. Sanırım bu yüzden sabitlik C ++ 'da bir sorun olurdu.
DDS

@MartinEpsz: "Ve herhangi bir hesaplanabilir işlevin olası tüm dönüş değerlerini söyleyebilen hesaplanabilir bir işlev yoktur". "Olası tüm dönüş değerlerini" kontrol etmenin yanlış bir yaklaşım olduğunu düşünüyorum. Denklemleri çözebilen matematiksel sistemler (maxima, mathlab) vardır, bu da fonksiyonlara benzer bir yaklaşım uygulamanın mantıklı olacağı anlamına gelir. Yani onu birkaç bilinmeyenli bir denklem olarak ele alalım. Sorunlar akış kontrolü + yan etkiler => çözülemeyen durumlardır. IMO, bunlar olmadan (işlevsel dil, atama / yan etki yok), hangi yol programının gideceğini tahmin etmek mümkün olurdu
SigTerm

16

Belirli bir fonksiyonun belirli bir değişkeni değiştirip değiştirmeyeceğini derleme zamanında algoritmik olarak bilemeyeceğinizi açıklamak için durdurma problemini çağırmanın gerekli olduğunu sanmıyorum.

Bunun yerine, bir işlevin davranışının genellikle derleyicinin önceden bilemeyeceği çalışma zamanı koşullarına bağlı olduğunu belirtmek yeterlidir. Örneğin

int y;

int main(int argc, char *argv[]) {
   if (argc > 2) y++;
}

Derleyici y, değiştirilip değiştirilmeyeceğini nasıl kesin olarak tahmin edebilir ?


7

Yapılabilir ve derleyiciler bazı işlevler için bunu her zaman yapıyor , bu örneğin basit satır içi erişimciler veya birçok saf işlev için önemsiz bir optimizasyondur.

İmkansız olan, genel durumda onu bilmektir.

Ne zaman bir sistem çağrısı veya başka bir modülden gelen bir işlev çağrısı veya potansiyel olarak geçersiz kılma yöntemine bir çağrı olduğunda, bazı bilgisayar korsanlarının ilgisiz bir değişkeni değiştirmek için yığın taşmasını kullanmasından düşmanca devralma dahil her şey olabilir.

Bununla birlikte, agresif optimizasyonlar gerçekleştirirken derleyicinin hayatını kolaylaştıracak const kullanmalı, globallerden kaçınmalı, işaretleyicilere referansları tercih etmeli, değişkenleri ilgisiz görevler için yeniden kullanmaktan kaçınmalısınız.


1
Doğru hatırlıyorsam, fonksiyonel programlamanın tüm noktası bu, değil mi? Yalnızca tamamen deterministik, yan etkisiz işlevler kullanarak, derleyiciler agresif optimizasyonlar, yürütme öncesi, yürütme sonrası, hafızaya alma ve hatta derleme zamanında yürütme yapmakta özgürdür. Yanıt verenlerin çoğunun görmezden geldiğini (veya kafasının karıştığını) düşündüğüm nokta , tüm programların iyi huylu bir alt kümesi için gerçekten mümkün olmasıdır . Ve hayır, bu alt küme önemsiz veya ilgi çekici değil, aslında çok kullanışlıdır. Ama mutlak genel durum için gerçekten imkansız.
Joe Pineda

Aşırı yükleme, bir derleme zamanı kavramıdır. Muhtemelen "geçersiz kılınan yöntemi" kastettiniz.
fredoverflow

@FredOverflow: evet, geçersiz kılmayı kastediyorum. Aşırı yükleme aslında bir derleme zamanı kavramıdır. Bunu tespit ettiğiniz için teşekkürler (tabii ki uygulama başka bir derleme biriminden geliyorsa, derleyici onu analiz etmekte hala sorun yaşayabilir, ancak kastettiğim bu değildi). Cevabı düzelteceğim.
kriss

6

Bunu açıklamanın birden fazla yolu vardır, bunlardan biri Duraklama Problemidir :

Hesaplanabilirlik teorisinde, durdurma problemi şu şekilde ifade edilebilir: "Rasgele bir bilgisayar programının açıklaması verildiğinde, programın çalışmasının bitip bitmediğine veya sonsuza kadar çalışmaya devam edip etmediğine karar verin". Bu, bir program ve bir girdi verildiğinde, programın o girdi ile çalıştırıldığında sonunda duracağına veya sonsuza kadar çalışıp çalışmayacağına karar verme sorununa eşdeğerdir.

Alan Turing, 1936'da, tüm olası program-girdi çiftleri için durdurma problemini çözmek için genel bir algoritmanın var olamayacağını kanıtladı.

Buna benzeyen bir program yazarsam:

do tons of complex stuff
if (condition on result of complex stuff)
{
    change value of x
}
else
{
    do not change value of x
}

Değeri xdeğişiyor mu? Bunu belirlemek için, önce do tons of complex stuffparçanın koşulun yanmasına neden olup olmadığını veya daha da basit bir şekilde durup durmadığını belirlemeniz gerekir. Bu, derleyicinin yapamayacağı bir şeydir.


6

Durma problemini doğrudan kullanmanın bir cevabı olmamasına gerçekten şaşırdım! Bu problemden durdurma problemine çok basit bir azalma var.

Derleyicinin, bir fonksiyonun bir değişkenin değerini değiştirip değiştirmediğini anlayabildiğini hayal edin. O zaman, programın geri kalanında x'in değerinin tüm çağrılarda izlenebileceğini varsayarak, aşağıdaki fonksiyonun y'nin değerini değiştirip değiştirmediğini kesinlikle söyleyebilir:

foo(int x){
   if(x)
       y=1;
}

Şimdi, sevdiğimiz herhangi bir program için onu şu şekilde yeniden yazalım:

int y;
main(){
    int x;
    ...
    run the program normally
    ...
    foo(x);
}

Dikkat edin, ancak ve ancak, programımız y'nin değerini değiştirirse, o zaman sonlandırır - foo (), çıkmadan önce yaptığı son şeydir. Bu, durma sorununu çözdüğümüz anlamına gelir!

Yukarıdaki indirgemenin bize gösterdiği şey, bir değişkenin değerinin değişip değişmediğini belirleme sorununun en az durma problemi kadar zor olduğudur. Durma sorununun tartışılmaz olduğu biliniyor, bu yüzden bu da olmalı.


Programımızın değerini değiştirirse neden sonlandırdığına dair düşüncenizi takip ettiğimden emin değilim y. Bana foo()hızlı bir şekilde dönüyor ve sonra main()çıkıyor gibi görünüyor . (Ayrıca, foo()tartışmadan arıyorsun ... bu benim kafa karışıklığımın bir parçası.)
LarsH

1
@LarsH: Değiştirilen program sona ererse, çağırdığı son işlev f idi. Y değiştirildiyse, f çağrılırdı (diğer ifadeler y'yi değiştiremez, çünkü yalnızca değişiklik tarafından tanıtıldı). Bu nedenle, y değiştirilirse, program sona erer.
MSalters

4

Bir işlev, derleyicinin kaynağını "görmediği" başka bir işlevi çağırır çağırmaz, ya değişkenin değiştiğini varsaymalıdır ya da aşağıda işler ters gidebilir. Örneğin, bunun "foo.cpp" içinde olduğunu varsayalım:

 void foo(int& x)
 {
    ifstream f("f.dat", ifstream::binary);
    f.read((char *)&x, sizeof(x));
 }

ve "bar.cpp" içinde bu var:

void bar(int& x)
{
  foo(x);
}

Derleyici x, bunun değişmediğini (veya daha uygun şekilde değiştiğini) nasıl "bilebilir" bar?

Eminim daha karmaşık bir şey bulabiliriz, eğer bu yeterince karmaşık değilse.


Derleyici, x çubuğu sabit'e referansla geçiş olarak aktarılırsa, x'in çubukta değişmediğini bilebilir, değil mi?
Cricketer

Evet, ancak bir const_castin foo eklersem, yine de xdeğişiklik olur - constdeğişkenleri değiştirmeyeceğinizi söyleyen sözleşmeyi ihlal etmiş olurum , ancak her şeyi "daha sabit" e dönüştürebileceğiniz ve const_castvarolduğundan, Dilin tasarımcıları, bazen constdeğerlerin değişmesi gerekebileceğine inanmak için iyi nedenler olduğu fikrine kuşkusuz sahiptiler .
Mats Petersson

@MatsPetersson: Eğer const_cast yaparsanız, derleyici olabilir, ancak bunu telafi etmek zorunda olmadığı için kırılan tüm parçaları tutacağınıza inanıyorum.
Zan Lynx

@ZanLynx: Evet, bunun doğru olduğuna eminim. Ama aynı zamanda, oyuncu kadrosu da var, bu da dili tasarlayan birinin "bir noktada buna ihtiyacımız olabileceği" fikrine sahip olduğu anlamına geliyor - bu, hiçbir işe yaramayacağı anlamına geliyor.
Mats Petersson

1

Bu genel olarak değişken olmadığını derleyici belirlemek için mümkün değildir olacak şekilde işaret edilmiş, değiştirilemez.

Const-lik kontrol ederken, ilgilenilen soru değişken eğer gibi görünüyor olabilir bir işlev tarafından değiştirilebilir. İşaretçileri destekleyen dillerde bu bile zor. Diğer kodun bir işaretçi ile ne yaptığını kontrol edemezsiniz, hatta harici bir kaynaktan okunabilir (olası olmasa da). Belleğe erişimi kısıtlayan dillerde, bu tür garantiler mümkün olabilir ve C ++ 'dan daha agresif optimizasyona izin verir.


2
Dillerde desteklenmesini dilediğim bir şey, kısa ömürlü, iade edilebilir ve kalıcı referanslar (veya işaretçiler) arasındaki ayrım olabilir. Geçici referanslar yalnızca diğer geçici referanslara kopyalanabilir, iade edilebilir referanslar geçici veya iade edilebilir referanslara kopyalanabilir ve kalıcı olanlar herhangi bir şekilde kopyalanabilir. Bir işlevin dönüş değeri, "döndürülebilir" parametreler olarak iletilen en kısıtlayıcı argümanlarla sınırlandırılacaktır. Pek çok dilde, bir referansı geçtiğinde, ne kadar süre kullanılabileceğini gösteren hiçbir şeyin bulunmamasının talihsiz olduğunu düşünüyorum.
supercat

Bu kesinlikle faydalı olacaktır. Elbette bunun için kalıplar vardır, ancak C ++ 'da (ve diğer birçok dilde) "hile yapmak" her zaman mümkündür.
Krumelur

. Bir özelliği kullanan kod, nesneyi işlemek için kullanılması gereken bir koda (geçici değişkenlerle birlikte) geçici bir referans
iletir

1

Soruyu daha spesifik hale getirmek için, kitabın yazarının aklında olabilecek aşağıdaki kısıtlamaların olabileceğini öneriyorum:

  1. Derleyicinin, bir değişkenin sabitliğine göre belirli bir fonksiyonun davranışını incelediğini varsayın. Doğruluk için, bir derleyicinin (aşağıda açıklandığı gibi takma ad nedeniyle) işlev başka bir işlevi çağırması durumunda değişkenin değiştiğini varsayması gerekir, bu nedenle 1 numaralı varsayım yalnızca işlev çağrıları yapmayan kod parçaları için geçerlidir.
  2. Değişkenin eşzamansız veya eşzamanlı bir etkinlik tarafından değiştirilmediğini varsayın.
  3. Derleyicinin, değişkenin değiştirilip değiştirilmeyeceğini değil, yalnızca değiştirilip değiştirilemeyeceğini belirlediğini varsayın. Başka bir deyişle, derleyici yalnızca statik analiz gerçekleştiriyor.
  4. Derleyicinin yalnızca doğru işleyen kodu düşündüğünü varsayın (dizi taşmaları / yetersizlikleri, kötü işaretçileri vb. Dikkate almıyor)

Derleyici tasarımı bağlamında, kod üretme doğruluğu ve / veya kod optimizasyonu bağlamında bir derleyici yazarının görüşünde 1,3,4 varsayımlarının mükemmel bir anlam ifade ettiğini düşünüyorum. Varsayım 2, uçucu anahtar kelimenin yokluğunda anlamlıdır. Ve bu varsayımlar aynı zamanda, önerilen bir cevabı yargılamayı çok daha kesin hale getirmek için soruyu yeterince odaklıyor :-)

Bu varsayımlar göz önüne alındığında, sabitliğin kabul edilememesinin temel nedeni, değişken takma addır. Derleyici, başka bir değişkenin const değişkenine işaret edip etmediğini bilemez. Aliasing, aynı derleme birimindeki başka bir işlevden kaynaklanıyor olabilir, bu durumda derleyici işlevlere bakabilir ve örtüşmenin oluşabileceğini statik olarak belirlemek için bir çağrı ağacı kullanabilir. Ancak, takma ad bir kitaplıktan veya başka bir yabancı koddan kaynaklanıyorsa, derleyicinin işlev girişi üzerine değişkenlerin adının olup olmadığını bilmesinin bir yolu yoktur.

Bir değişken / bağımsız değişken sabit olarak işaretlenmişse, takma ad ile değiştirilmemesi gerektiğini, ancak bir derleyici yazarı için bu oldukça riskli olduğunu iddia edebilirsiniz. Bir insan programcının, bir değişken sabitini, örneğin tüm sistemin, işletim sisteminin veya bir kütüphanenin davranışını bilmediği büyük bir projenin, kazanılan bir değişkeni gerçekten bilmesinin bir parçası olarak bildirmesi bile riskli olabilir. t değiş.


0

Bir değişken bildirilmiş olsa bile const, kötü yazılmış bir kodun üzerine yazabileceği anlamına gelmez.

//   g++ -o foo foo.cc

#include <iostream>
void const_func(const int&a, int* b)
{
   b[0] = 2;
   b[1] = 2;
}

int main() {
   int a = 1;
   int b = 3;

   std::cout << a << std::endl;
   const_func(a,&b);
   std::cout << a << std::endl;
}

çıktı:

1
2

Bunun nedeni olur ave byığın değişkenler ve b[1]sadece aynı bellek konumu olur a.
Mark Lakata

1
-1. Tanımsız Davranış, derleyicinin davranışındaki tüm kısıtlamaları kaldırır.
MSalters

Olumsuz oylama konusunda emin değilim. Bu, OP'nin orijinal sorusuna giden bir örnektir, bir derleyicinin consther şey etiketlenmişse bir şeyin gerçekten olup olmadığını neden anlayamamasıdır const. Bunun nedeni, tanımsız davranışın C / C ++ 'nın bir parçası olmasıdır. Durma sorunundan veya dış insan girdisinden bahsetmektense, sorusuna cevap vermenin farklı bir yolunu bulmaya çalışıyordum.
Mark Lakata

0

Yorumlarımı genişletmek gerekirse, o kitabın metni belirsizdir, bu da konuyu gizlemektedir.

Yorumladığım gibi, bu kitap şöyle demeye çalışıyor: "Haydi, yazılabilecek akla gelebilecek her C ++ işlevini yazmak için sonsuz sayıda maymun bulalım. Bir değişken seçersek (maymunların yazdığı belirli bir işlev) durumlar olacaktır. kullanırsa, fonksiyonun bu değişkeni değiştirip değiştirmeyeceğini çözemeyiz. "

Elbette, herhangi bir uygulamadaki bazı (hatta birçok) işlev için bu, derleyici tarafından ve çok kolay bir şekilde belirlenebilir. Ama hepsi için değil (veya zorunlu olarak çoğu).

Bu işlev kolayca analiz edilebilir:

static int global;

void foo()
{
}

"foo" açıkça "global" i değiştirmez. Hiçbir şeyi değiştirmez ve bir derleyici bunu kolayca çözebilir.

Bu işlev bu şekilde analiz edilemez:

static int global;

int foo()
{
    if ((rand() % 100) > 50)
    {
        global = 1;
    }
    return 1;

"Foo" 'nun eylemleri çalışma zamanında değişebilen bir değere bağlı olduğundan , derleme zamanında "global" i değiştirip değiştirmeyeceği açık bir şekilde belirlenemez .

Tüm bu kavramı anlamak, bilgisayar bilimcilerinin sandığından çok daha basit. İşlev, çalışma zamanında değişen şeylere bağlı olarak farklı bir şey yapabilirse, çalışana kadar ne yapacağını hesaplayamazsınız ve her çalıştığında farklı bir şey yapabilir. Kesin olarak imkansız olsun ya da olmasın, açıkça imkansız.


Söyledikleriniz doğrudur, ancak derleme sırasında her şeyin bilindiği çok basit programlar için bile hiçbir şeyi kanıtlayamazsınız, programın duracağını bile. Bu durma problemidir. Örneğin, Hailstone Sequences en.wikipedia.org/wiki/Collatz_conjecture'a dayalı bir program yazabilir ve bir programa yakınsarsa onu gerçek duruma getirebilirsiniz. Derleyiciler bunu yapamazlar (çoğu durumda taşacağı gibi) ve matematikçiler bile bunun doğru olup olmadığını bilemezler.
kriss

Eğer demek istediğin "vardır bazı şey ispat edemez kendisi için çok basit görünümlü programları" Ben tamamen katılıyorum. Ancak Turing'in klasik Duraklama Problemi kanıtı, esas olarak bir programın bir çelişki oluşturmak için durup durmadığını söyleyebilmesine dayanır. Bu matematik olduğu için uygulama değil. Kesinlikle, derleme sırasında belirli bir değişkenin değiştirilip değiştirilmeyeceğini ve programın durup durmayacağını statik olarak belirlemek tamamen mümkün olan programlar vardır. Matematiksel olarak ispatlanabilir olmayabilir, ancak bazı durumlarda pratik olarak elde edilebilir.
El Zorko
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.