`Main` neden int veya void yerine bir double veya String döndüremiyor?


38

C, C ++ ve Java gibi birçok dilde mainyöntemin / fonksiyon bir dönüş türü vardır voidya intama, doubleya String. Bunun arkasındaki nedenler neler olabilir?

Çünkü bunu yapamaz biraz biliyorum mainçalışma zamanı kitaplığı tarafından çağrılır ve bazı sözdizimi gibi beklediğini int main()ya int main(int,char**)biz o sopa zorunda.

Öyleyse benim sorum şu: neden sahip mainolduğu imzası var, niçin farklı değil?


15
Çift getiri değeri ne anlama gelir ? Bir dize dönüş değeri ne anlama gelir ?

1
ki bunun bir anlamı olmadığını anlayın. Başka sebepler ve sözleşmeler?
JAVA

1
Bunun bir anlamı olmadığını düşünüyorum, çünkü evrensel olarak normal çıkış için 0, anormal için sıfır olmayan bir değer seçildi. Geniş bir dil desteği olan en basit veri türü olarak bir int seçildi. @ delnan
JAVA

@sunny Unix benzeri işletim sistemleriyle olan deneyimimden elde ettiklerimden 0, "normal çıkış" (0 hatalar) olarak kullanılıyor, çünkü diğer tamsayı değerleriyle karşılaştırıldığında kesin değil. Modern dillerin çoğu (hepsi değil) C'ye benzer olacak şekilde tasarlandığından (arkalarında tasarlanmadıysa) ve C Unix'i yazmak için kullanıldığından, KnR tarafından verilen tarihi bir karar olduğunu söyleyebilirim.
Jamie Taylor

3
@ güneşli "geniş çapraz dil uyumluluğu" bir sorun değildi. C ve UNIX birlikte yazılmıştır. Diğer birçok dilin giriş yapmasının nedeni, UNIX veya UNIX benzeri ortamlarda çalışmak üzere tasarlanmış olmalarıdır.

Yanıtlar:


83

Dönüş değeri mainişletim sistemine ( herhangi bir işletim sistemine) tek ve tutarlı bir şekilde iletilir . İşletim sisteminin bilmesi gereken bilgiler "program başarıyla sonlandırıldı mı veya bir hata mı oldu?"

Bu bir dize ise, yanıt farklı dillerde zorlaşır. Bir Pascal dizesinin içindekiler (ilk bayt uzunluktur) ve bir FORTRAN dizgisi (sabit, bir değere yastıklı) ve bir C dizgisi (boş sonlandırılmış) hepsi farklıdır. Bu, işletim sistemine tutarlı bir değer döndürmeyi zorlaştırır. Bunun çözüldüğünü varsayarak, işletim sisteminin programla ilgili sorusunu cevaplamak için ne yapardınız? Dize karşılaştırmaları hatalarla doludur ("başarı" vs "Başarı") ve hata bir insan için daha faydalı olsa da, işletim sistemi veya başka bir programın (kabuk) ele alınması daha zordur. Hatta kendilerinde bile önemli farklılıklar vardı - EBCDIC (tüm kod sayfalarıyla birlikte) ASCII.

Şamandıralar ve çiftler, verileri işletim sistemine (ve kabuk) iletmek için tamsayıya ek bir değer sağlamaz. Çoğunlukla, bilgisayarın bu kısımlarının hiçbiri kayan nokta sayılarıyla ilgilenmez. Çiftler de karşılaştırmayı zorlaştıracak şekilde numaralandırılamaz. Numaralandırılmamak, hatanın ne olduğunu bildirmeyi sağlar (başarı için özel bir değer seçtiniz varsayarak). Yine, kayan noktalar tutarlı değil - 8 bitlik bir makinedeki bir şamandıra, 16 bit ve 32 bit'lik bir makinedeki şamandıradan farklıydı (ve bunlar sadece 'normal' olanlardır - IBM dahilinde bile, kayan nokta standartlaştırılmadı) 1980'lere kadar aynı üreticinin makineleri arasında). Ve sonra ondalık ve ikili bilgisayarlara sahipsiniz. Kayan nokta değerleri tutarlı değil ve geri anlamlı veri sağlamaz.

Bu bizi seçenek olarak bayt ve tamsayıya bırakıyor. Kurulan kongre '0' başarıydı ve başka bir şey bir hataydı. Bir tamsayı, hatayı bildirmek için bir bayttan daha fazla alan sağlar. Bu (dönüş 1 araçlarının XYZ, 2 vasıtasıyla vb .. ABC 3 dönüşü, DEF aracı, dönüşü) (veya bayrak olarak kullanılabilir sayılabilir 0x0001Bu başarısız vasıtasıyla, 0x0002başarısız vasıtasıyla 0x0003hem bu ve başarısız aracı). Bunu sadece bir bayt ile sınırlamak bayrakların kolayca tükenmesine neden olabilir (sadece 8), bu nedenle karar muhtemelen bir tamsayı kullanmaktı.


2
Sanırım ana c / c ++ runtime kütüphanesi tarafından os çağrılmadan önce çağrılır ve bu kod bizim kodumuzla birlikte yüklenir ve os @ MichaelT tarafından çağrılır
JAVA

5
main()farklı işletim sistemlerinde farklı yollar çağrılır. C'de, main () yöntemi başlangıçta nasıl adlandırılır? buna gider.

22
Anlaşılması gereken nokta main, herhangi bir programdaki diğer fonksiyonlardan farklı olarak, programcı tarafından tanımlanan bir protokolün parçası değil, ana bilgisayarla (OS) arayüz oluşturmak için kullanılan protokolün olduğunu düşünüyorum. Seçme şansın yok çünkü seçmen asla senin olmadı. Daha pragmatik bir düzeyde, UNIX bir işlem tarafından döndürülecek bir int bekler ve böylece C-UNIX protokolü tam olarak bunu yapar. Argüman geçişi için benzer bir argüman yapılabilir: C sadece sayıları argüman olarak geçiren bir işletim sistemi / ana bilgisayar için icat edilmişse (örn. Komut satırı yok), argümanlar dize yerine ints olur.
Euro Micelli

2
IBM, EBCDIC'den bilgisayarlarına kod sayfaları kavramını aldı. IBM 5150'nin piyasaya sürülmesinden 35 yıl sonra hala devam ediyorlar. 7-bit ASCII kod sayfası az, ancak 8-bit karakter kodları, ayarlara bağlı olarak tek bir bilgisayarda bile birçok farklı şekilde yorumlanabilir. - Çok baytlı kodlamaları kodlayan kod sayfaları tek başına. Bu yüzden , ikinci paragrafın son cümlesinde neyi sevdiğinizden daha da kötü .
Bir CVn

@EuroMicelli aslında bunun için çok güzel bir bilgi. :)
JAVA

27

Eh, olabilir .

Örneğin, Plan 9 işletim sisteminde kullanılan C lehçesinde mainnormal olarak bir voidişlev olarak bildirilir , ancak çıkış durumu exits()işleve bir dize işaretçisi geçirilerek çağrı ortamına döndürülür . Boş dize başarısını gösterir ve boş olmayan herhangi bir dize bir tür başarısızlığı belirtir. Bu olabilir alarak uygulanmıştır mainbir dönüş char*sonucu.

Ve o kesinlikle bir bir sistemi uygulamak mümkün olacağını floatveya doubleçıkış durumuna.

Neden Yani int? Bu sadece bir kongre meselesi - ve işletim sistemleri ve altlarında çalışan programların ortak bir kongreye uyması konusunda muazzam bir değer var .

Unix kuralı, bir tamsayı durum kodu kullanmaktır, 0 ile ifade edilen başarı ve sıfır olmayan ifade ile başarısızlık (tipik olarak başarılı olmanın sadece bir yolu var, ancak başarısız olmanın birden fazla yolu var). Bu konvansiyonun Unix’le mi yapıldığını bilmiyorum; Daha önceki işletim sistemlerinden geldiğinden şüpheleniyorum.

Kayan nokta daha zor bir kongredir, çünkü (a) kayan nokta desteği evrensel değildir, (b) kayan nokta değerleri ile hata koşulları arasında bir harita tanımlamak daha zordur, (c) farklı sistemler farklı kayan nokta kullanırlar. nokta gösterimleri ve (d) yalnızca programınızın çıkış durumundaki bir yuvarlama hatasını izlemenin eğlenceli olduğunu hayal edin. Öte yandan, tam anlamıyla hata kodlarının numaralandırılması için tam anlamıyla ödünç verenler kendilerini çok iyi ödünç veriyor.

Bahsettiğim gibi, Plan 9, dizeleri kullanır, ancak bu, bellek yönetimi, karakter kodlaması, vb. İçin biraz karmaşıklık getirir. Bildiğim kadarıyla, Plan 9'un uyguladığı zaman yeni bir fikirdi ve mevcut olanın yerine geçmedi. yaygın kongre.

(Bu arada, C ++ ' mainda yalnızca geri dönebilir intve C'ye void mainyalnızca derleyici özel olarak destekliyorsa izin verilir. Birçok derleyici yazdığınızda yüksek sesle şikayet etmez void main, ancak bunun yanlış olduğunu söylemek çok hafif bir abartıdır .)


9

Ana yöntem tarafından döndürülen değer bir "çıkış kodu" dur. Programın beklendiği gibi bitip bitmediğini test etmek için arayan uygulaması (normalde bash) tarafından kullanılır. Bir tamsayı döndürmek, işletim sistemi düzeyinde yapmanın en kolay yoludur. Double, hata kodu için bir anlam ifade etmiyor ve bir String'in işletim sistemi seviyesinde (ZK) olmaması zor.


3
Bir tamsayı olmasa da neden bir dizginin çöp toplanması gerekiyor?
Brad

4
@Brad, karakter dizileri kendilerine göre değişken uzunluklara sahiptir ve özünde bir karakter olabilen veya binlerce olabilen bir diziyi geri almakla aynı olacaktır. Dinamik bellek bir acı olurken, int kullanımı zor olmayan sabit bir boyutta.
JB King,
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.