Neden main buraya 0 döndürmüyor?


116

Sadece okuyordum

ISO / IEC 9899: 201x Komite Taslağı - 12 Nisan 2011

5.1.2.2.3 Program sonlandırma altında bulduğum

..reaching the } that terminates the main function returns a value of 0. 

bu, içinde herhangi bir return ifadesi belirtmezseniz main()ve program başarılı bir şekilde çalışırsa, main'in kapanış parantezinde} 0 döndürür anlamına gelir.

Ancak aşağıdaki kodda herhangi bir dönüş ifadesi belirtmiyorum, ancak 0 döndürmüyor

#include<stdio.h>
int sum(int a,int b)
{
return (a + b);
}

int main()
{
    int a=10;
    int b=5;
    int ans;    
    ans=sum(a,b);
    printf("sum is %d",ans);
}

derleme

gcc test.c  
./a.out
sum is 15
echo $?
9          // here it should be 0 but it shows 9 why?

69
Özellikleri okumak için sabrınız olduğu için +1 .....
Asher

16
gcckendi başına (4.6.2 sürümü için) çok benzer ancak C'ye pek benzemeyen bir dili derler. GnuC89'u C89'a dayalı "gevşek" bir dil olan GnuC89'u derler.
pmg

2
Üzerinde parantez returnifadesi in sum()gereksizdir. int main()olmalıdır int main(void).
Keith Thompson

24
Karışıklık! = Yazım hatası. Klavyemde '0' ve 'o', kolayca ikincisi olması için yeterince yakın. ;-)
The111

2
IMHO, derleyiciyi örtük bir "dönüş 0" ekleyerek "ana" işlevi özel bir şekilde yönetmeye zorladığı için oldukça aptalca bir belirtimdir. Dolayısıyla, "ana" adlı bir işlev biraz farklı bir şekilde davranır. Derleme zamanı kontrolleri ("dönüş değeri yok" ve benzer) ne olacak?
Giuseppe Guerrini

Yanıtlar:


141

Bu kural, C standardının 1999 versiyonunda eklendi. C90'da, döndürülen durum tanımsızdır.

-std=c99Gcc'ye geçerek etkinleştirebilirsiniz .

Bir yan not olarak, ilginç bir şekilde 9 döndürülür çünkü geri dönüşü printf9 karakter yazmıştır.


40
Veya return 0;kapanıştan önce ekleyebilirsiniz }. Zararsızdır ve programınızı eski derleyiciler için taşınabilir hale getirir.
Keith Thompson

2
@ Mr.32: iyi bir gözlem, printf () dizgenin uzunluğunu döndürür, böylece ana dizinin "dönüşü" olan 9 olur (-std = c99 kullanmadan).
Hicham

1
@cnicutar: Fonksiyonlar tipik olarak yığın üzerinde küçük değerler döndürmez - çünkü sadece bir hareket ve dönüşten ziyade bir pop, bir itme ve bir sıçrama içerir - bu nedenle neredeyse kesinlikle bir kayıttır, eaxözellikle x86'da.
Jon Purdy

8
Evet, x86 API genellikle eaxyazmaç aracılığıyla tamsayı benzeri bir değer döndürür . Daha fazla bilgi için en.wikipedia.org/wiki/X86_calling_conventions#cdecl adresine bakın .
Sylvain Defresne

2
Birkaç kez "int foo (void) {bar ();}" gibi bir kod gördüm, burada "return bar ()" kastedildi. Bu kod, bariz hataya rağmen çoğu işlemcide gayet iyi çalışıyor.
ugoren

15

printfGerçekte yazdırılan karakter sayısı olan dönüş değeri döndürür .


soru konsolda neyin yazdırıldığından bahsetmiyor programı çalıştırırken, programın dönüş değerinden bahsediyor: (bunu linux'ta schell komutu ile alabilirsiniz: echo $? ve pencerelerde echo% errorlevel% )
Hicham

1
@eharvest %errorlevel%Windows'ta nasıl kontrol edeceğimi bilmesem de, linux'ta çıkış kodu ile dönüş değeri arasında herhangi bir fark var mainmı?
Summer_More_More_Tea

1
@eharvest: Cevap, konsolda neyin yazdırıldığından da bahsetmiyor. Bu bahsediyor dönüş değeri arasında printfbu durumda o andan itibaren çıkış kodu olarak "terfi" alır 9 olan mainbelirli gcc sürümlerini kullanırken nasılsa.
AH

afedersiniz. benim hatam. Haklısın. bu yanıtı çok hızlı okudum: /
Hicham

1
Bunun garanti edilmediğini unutmayın . C89 / C90'da, bu durumda döndürülen durum tanımsızdır ; herhangi bir şey olabilir. 9 döndürür çünkü derleyici başka bir şey döndürmek için hiçbir çaba sarf etmedi. Diğer derleyiciler muhtemelen farklı davranacaktır.
Keith Thompson

6

Bir işlevin dönüş değeri normalde cpu'nun eax yazmacında saklanır, bu nedenle "return 4;" genellikle derlenir

mov eax, 4;
ret;

ve dönüş x (derleyicinize bağlı olarak) şöyle bir şey olacaktır:

mov eax, [ebp + 4];
ret;

Eğer bir dönüş değeri belirtmezseniz, derleyici yine de "ret" yi tükürecektir ancak eax değerini değiştirmez. Böylece arayan kişi eax kaydında daha önce bırakılanın dönüş değeri olduğunu düşünecektir. Bu örnek için genellikle printf dönüş değeri olur, ancak farklı derleyiciler farklı makine kodu üretir ve bazı kayıtları farklı şekilde kullanır.

Bu basitleştirilmiş bir açıklamadır, farklı arama kuralları ve hedef platformlar hayati bir rol oynayacaktır, ancak örneğinizde 'perde arkasında' neler olduğunu açıklamak için yeterli bilgi olmalıdır.

Montajcı hakkında temel bir anlayışınız varsa, farklı derleyicilerin demontajını karşılaştırmaya değer. Bazı derleyicilerin eax yazmacını bir güvenlik önlemi olarak temizlediğini görebilirsiniz.


11
Derleyici olabilir bunu. Tanımsız. Bunun yerine sizi bir yazıcı kartuşuyla kafanızdan vurmayı seçebilir.
Orbit'te Hafiflik Yarışları

@LightnessRacesinOrbit undefined, öngörülemeyen ile aynı değildir, yani "derleyici X yaparsa standart uyumlu olacaktır" mantıksal olarak takip etmez "derleyici X yapabilir"
Owen

@Owen: Bunu tanımlayan standart pasajı alıntılayın.
Orbit'te Hafiflik Yarışları

2
@LightnessRacesinOrbit Özür dilerim tam olarak takip edemiyorum. Sanırım gerçekten söylemek istediğim şey, bu cevapta sağlanan noggin182 gibi başlık altı görüşlerin hata ayıklama için inanılmaz derecede yararlı olduğunu düşünüyorum. Programınız beklenmedik sonuçlar üretirken, çoğu zaman bunların nereden geldiklerini veya kodun neresine bakacağınızı bilmiyorsunuz ve uygulama ayrıntılarını anlamak sizi doğru yöne yönlendirebilir.
Owen

@Owen Ben aksini iddia etmedim
Lightness Races in Orbit
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.