Main () C ve C ++ 'da ne döndürmelidir?


695

28
Yine de oldukça belirsiz olduğunu düşünüyorum. Benim için "en verimli" yi tanımlayın. Ne anlamda verimli? Daha az hafıza almak anlamında mı? Daha hızlı koşmak anlamında mı? Yararlı cevapları görebiliyorum ama hala sorunun oldukça kötü ifade edildiğini düşünüyorum.
Onorio Catenacci

7
Pish posh, verimli bağlamı burada, özellikle örneklerle ('verimli' tanımını açıklığa kavuşturacak olan) açıktır. Umarım fakir tampon bir deliğe sürünmez ve soruyu tamamen pişman etmez. Boşluk veya int'den bağımsız olarak bir değer döndürüldüğünü söyleyebiliriz, bu nedenle dosya boyutu, yürütülen işlemler veya ayrılan bellek üzerinde hiçbir etkisi yoktur. Ve çoğu işletim sistemindeki insanlar başarıya 0 ve başka bir başarı ya da başarısızlık üzerine başka bir şey döndürme eğilimindedir, ancak standart yoktur. Sonuçta, hiçbir belirgin şekilde verimlilikte fark yoktur.
Kit10

"doğru (en verimli)" bir anlam ifade etmiyor. Verimli bir şeydir, doğru başka bir şeydir.mainbir kez çağrılır (ve C ++ 'da yalnızca bir kez çağrılabilir: özyineleme yok). Yürütmenin çok fazla zaman geçirmesini istemiyorsanız main, programı çok kez çağırmayın: programı tekrarlamayı uygulayın.
Kaz

2
Yanıtların hiçbirinin, söyleyebildiğim kadarıyla, #includeifadeler de dahil olmak üzere tam olarak çalışan bir örnek sunmaması ilginç buluyorum
puk

3
Dönüş değerleri işletim sistemi olmayan bir platformda anlamsızdır. Hiçbir şeye geri dönmüyorsunuz. Eğer bir vurursanız returniçinde main(...)gömülü bir cihazda, sistem beklenmeyen bir durumda gider ve çamaşır makinesi kendinin farkında olmak ve sizi öldürmeye çalışacaktır. Yani, void main()bu durumda kullanıyoruz. Bu çıplak metal gömülü endüstri standardı bir uygulamadır.
3Dave

Yanıtlar:


570

İçin dönüş değeri mainprogramın nasıl çıktığını gösterir. Normal çıkış, konumundan 0 dönüş değeriyle temsil edilir main. Anormal çıkış sıfır olmayan bir dönüşle bildirilir, ancak sıfır olmayan kodların nasıl yorumlandığına dair bir standart yoktur. Başkaları tarafından belirtildiği gibi void main(), C ++ standardı tarafından yasaklanmıştır ve kullanılmamalıdır. Geçerli C ++ mainimzaları:

int main()

ve

int main(int argc, char* argv[])

eşdeğer

int main(int argc, char** argv)

Ayrıca, C ++ ' int main()da bir return-ifadesi olmadan bırakılabileceğini belirtmek gerekir, bu noktada varsayılan olarak 0 döndürür. İster return 0;ihmal veya olmasın tartışmaya açıktır edilmelidir. Geçerli C programı ana imzalarının aralığı çok daha fazladır.

Verimlilik mainişlevle ilgili bir sorun değildir . C ++ standardına göre yalnızca bir kez girilebilir ve bırakılabilir (programın başlangıcı ve sonlandırılması işaretlenir). C için yeniden girişe main()izin verilir, ancak bundan kaçınılmalıdır.


69
ana birden fazla kez girilebilir / bırakılabilir, ancak bu program muhtemelen herhangi bir tasarım ödülü kazanamaz;)
korona

13
C99 ayrıca, main () işlevinin sonuna ulaşan 0 ile eşdeğer olan C ++ yanlış özelliğine sahiptir - eğer main () int ile uyumlu bir tür döndürmek için tanımlanmışsa (bölüm 5.1.2.2.3).
Jonathan Leffler

62
main yeniden girme geçerli C ++ değil. Standartta açıkça, 3.6.1.3 devletlerin 'ana bir programda kullanılmayacaktır'
workmad3

117
stdlib.h bu amaçla EXIT_SUCCESS ve EXIT_FAILURE sağlar
Clay

20
0 ve sıfır olmayan kodlar doğrudur ancak kodunuzu okuyan biri için anlamsızdır. Bu soru, insanların geçerli / geçersiz kodların ne olduğunu bilmediklerinin kanıtıdır. EXIT_SUCCESS / EXIT_FAILURE çok daha net.
JaredPar

169

Kabul edilen cevap C ++ için hedeflenmiş gibi görünüyor, bu yüzden C ile ilgili bir cevap ekleyeceğimi düşündüm ve bu birkaç şekilde farklı.

ISO / IEC 9899: 1989 (C90):

main() şunlardan biri olarak beyan edilmelidir:

int main(void)
int main(int argc, char **argv)

Veya eşdeğer. Örneğin int main(int argc, char *argv[]), ikincisine eşdeğerdir. Ayrıca, intvarsayılan olarak dönüş türü atlanabilir.

Bir uygulama izin veriyorsa, main() başka yollarla bildirilebilir, ancak bu, program uygulamasını tanımlar ve artık kesin olarak uymaz hale getirir.

Standart, kesinlikle uygun olan (yani, uygulama tanımlı davranışa bağlı olmayan) geri dönüş için 3 değer tanımlar: 0ve EXIT_SUCCESSbaşarılı bir sonlandırma ve EXIT_FAILUREbaşarısız bir sonlandırma için. Diğer değerler standart değildir ve uygulama tanımlıdır. tanımlanmamış davranışı önlemek için sonunda main()açık bir returnifade olmalıdır .

Son olarak, main()bir programdan arama yaparken standartlar açısından yanlış bir şey yoktur .

ISO / IEC 9899: 1999 (C99):

C99 için, her şey yukarıdaki ile aynıdır:

  • intDönüş türü ihmal edilemez.
  • İade ifadesini buradan çıkarabilirsiniz main(). Yaparsanız ve main()bitirirseniz, bir örtük var return 0.

1
@Lundin Birisinin standartlara uygun olmayan programları kabul eden bir derleyici yapmasına veya standartlara uygun olmayan bir derleyiciye sahip olmasına izin vermek için bir alıntıya ihtiyacınız olduğunu düşünmüyorum. Bu ortak bilgi ve sağduyu
KABoissonneault

4
@KABoissonneault Uygulama tanımlı davranış, tamamen belgelenmemiş davranışın aksine standarttan bir terimdir. Uygulama tanımlı davranış olarak listelenen bir şey uygularsanız, standarda uymaya devam edersiniz. Alıntılanan bu örnekte, C89 sadece bir şeyleri maviden çıkarmak olmadığını kanıtlamak için böyle bir uygulama tanımlı davranış, dolayısıyla alıntı yapma ihtiyacı listelemektedir.
Lundin

1
@Lundin Bunu yanlış görüyorsun. Bahsettiğimiz şey, uygulama tanımlı davranış değil, seçtikleri takdirde standarttan sapan bir uygulamadan bahsediyoruz. Daha çok ebeveynlerine itaatsizlik eden bir çocuk gibidir: bir çocuğun ebeveynlerinin söylediklerine karşı nasıl gidebileceğini söylemek için ebeveynlerden bir alıntıya ihtiyacınız yoktur. Sadece çocuğun bunu seçtiği anda, artık ebeveynlerinin guildeline'larına uymadığını biliyorsunuz
KABoissonneault

2
@KABoissonneault Yorumumda alıntıladığım kısım kesinlikle uygulama tanımlı davranış hakkında ( standart dışı derleyici uzantılarının aksine ). Bu yüzden uygulama tanımlı davranıştan bahsediyorum. Başka bir şey hakkında bir monolog yaşıyorsanız, iyi şanslar.
Lundin

1
@Lundin Sanırım alıntı ifadeler kafa karıştırıcı (dedikleri kısmı "ama bu program uygulamasını tanımlanmış yapar") ama kişinin standart olmayan davranış hakkında konuştuğundan eminim ("Eğer bir uygulama izin verir "ve" ve artık [standarda] "tam olarak uygun değildir) gerçek uygulama tanımlı davranışın aksine. Kişi kesinlikle cevaplarını yeniden yazmalı, ancak yine de standarttan bir teklif gerekli olduğunu
düşünmüyorum

117

Standart C - Barındırılan Ortam

Barındırılan bir ortam için (bu normaldir), C11 standardı (ISO / IEC 9899: 2011) diyor ki:

5.1.2.2.1 Programın başlatılması

Program başlangıcında çağrılan işlev adlandırılır main. Uygulama, bu işlev için herhangi bir prototip bildirmez. Geri dönüş tipi intve parametresiz olarak tanımlanmalıdır :

int main(void) { /* ... */ }

veya iki parametre ile (burada argcve olarak adlandırılırlar argv, ancak bildirildikleri işlev için yerel olduklarından herhangi bir ad kullanılabilir):

int main(int argc, char *argv[]) { /* ... */ }

veya eşdeğer; 10) veya başka bir uygulama tarafından tanımlanan şekilde.

Bildirilirlerse, ana işleve ilişkin parametreler aşağıdaki kısıtlamalara uymalıdır:

  • Değeri argcnegatif olmayacaktır.
  • argv[argc] boş gösterici olacaktır.
  • Değeri ise argcsıfırdan büyük olduğu, dizi üyeleri argv[0]ile argv[argc-1] , içerme , program başlatılmadan önce ana bilgisayar ortamı tarafından uygulama tanımlı değerler verilen dizelere işaretçiler içerecektir. Amaç, programın başlatılmasından önce, barındırılan ortamın başka bir yerinden belirlenen program bilgilerini sağlamaktır. Ana bilgisayar ortamı, hem büyük hem de küçük harf içeren harflerle dizeleri sağlayamıyorsa, uygulama dizelerin küçük harfle alınmasını sağlamalıdır.
  • Değeri argcsıfırdan büyükse, ile gösterilen dize argv[0] program adını gösterir; argv[0][0]ana bilgisayar ortamında program adı yoksa boş karakter olacaktır. Değeri argcbirden büyükse, argv[1]üzerinden işaret edilen dizeler argv[argc-1] program parametrelerini temsil eder.
  • Dizinin işaret ettiği parametreler argcve argvdizeler argvprogram tarafından değiştirilebilir ve program başlatma ile program sonlandırılması arasında son kaydedilen değerlerini korur.

10) Böylece, intolarak tanımlanmış bir typedef adı ile değiştirilebilir intveya türü ve benzeri argvyazılabilir char **argv.

C99 veya C11'de program sonlandırma

Döndürülen değer main(), uygulama tanımlı bir şekilde 'çevreye' iletilir.

5.1.2.2.3 Program sonlandırma

1 mainİşlevin dönüş türü uyumlu intbir türse, ilk çağrıdan mainişleve geri dönüş exit, mainişlevin bağımsız değişken olarak döndürdüğü değerle işlevin çağrılmasına eşdeğerdir ; 11) işlev }sona erdirilen maindeğere ulaşmak 0 değerini döndürür. Dönüş türü ile uyumlu değilse int, ana bilgisayar ortamına döndürülen sonlandırma durumu belirtilmez.

11) 6.2.4'e uygun olarak, otomatik saklama süresine sahip nesnelerin kullanım ömürleri main , önceki durumda, sonrakinde bulunmadıkları yerlerde bile sona ermiş olacaktır.

Bunun 0'başarı' olarak zorunlu tutulduğunu unutmayın . İsterseniz EXIT_FAILUREve EXIT_SUCCESSarasından kullanabilirsiniz <stdlib.h>, ancak 0 iyi kurulmuş ve 1 de olabilir. Ayrıca bkz. 255'ten büyük Çıkış kodları - mümkün mü? .

C89'da (ve dolayısıyla Microsoft C'de), main()işlev döndürülür ancak bir dönüş değeri belirtmezse ne olacağına dair bir ifade yoktur ; bu nedenle tanımlanmamış davranışa yol açar.

7.22.4.4 exitİşlev

¶5 Son olarak, kontrol ana bilgisayara geri döndürülür. Değeri statussıfır veya EXIT_SUCCESSdurum başarılı sonlandırmanın uygulama tanımlı bir formu döndürülür. Değeri: statusise EXIT_FAILURE, başarısız sonlandırma durumunun uygulama tanımlı bir formu döndürülür. Aksi takdirde, döndürülen durum uygulama tanımlıdır.

Standart C ++ - Barındırılan Ortam

C ++ 11 standardı (ISO / IEC 14882: 2011) diyor ki:

3.6.1 Ana işlev [basic.start.main]

Program1 Bir program, programın belirlenmiş başlangıcı olan main adlı küresel bir işlev içerecektir. [...]

İmplementation2 Bir uygulama ana işlevi önceden tanımlamamalıdır. Bu işlev aşırı yüklenmemelidir. İnt türünde bir dönüş türüne sahip olacaktır, ancak aksi takdirde türü uygulama olarak tanımlanmıştır. Tüm uygulamalar, aşağıdaki ana tanımların her ikisine de izin verecektir:

int main() { /* ... */ }

ve

int main(int argc, char* argv[]) { /* ... */ }

İkinci formda argc, programın çalıştırıldığı ortamdan programa iletilen argüman sayısı olacaktır. Eğer argcbu argümanlar temin edilecektir sıfırdan farklıysa argv[0] aracılığıyla argv[argc-1]boş sonlandırılmış baytlı şeritlerinin başlangıç karakterler (NTMBSs) (17.5.2.1.4.2) işaretçiler olarak ve argv[0]kullanılan adını gösteren bir NTMBS ilk karaktere gösterici olacaktır programı çağırın veya "". Değeri argcnegatif olmamalıdır. Değeri argv[argc] 0 olmalıdır. [Not: Sonradan başka (isteğe bağlı) parametrelerin eklenmesi önerilir argv. —End not]

¶3 Fonksiyon mainbir program dahilinde kullanılmamalıdır. Bağlantısı (3.5) mainuygulama tanımlıdır. [...]

¶5 Bir dönüş ifadesi, ana işlevi terk etme (otomatik saklama süresi olan herhangi bir nesneyi yok etme) ve std::exitargüman olarak dönüş değeri ile çağırma etkisine sahiptir . Eğer kontrol bir return deyimi ile karşılaşmadan ana sonuna ulaşırsa, etkisi

return 0;

C ++ standardı açıkça "Bu [ana işlev] bir tür dönüş türüne sahip olmalıdır int, ancak aksi takdirde türü uygulama tanımlıdır" ve seçenek olarak C standardıyla aynı iki imzayı gerektirir. Dolayısıyla, bir 'void main ()' C ++ standardı tarafından doğrudan izin verilmez, ancak alternatif olmayan standart olmayan bir uygulamayı durdurmak için yapabileceği hiçbir şey yoktur. C ++ 'ın kullanıcının aramasını yasakladığını unutmayın main(ancak C standardı bunu yapmaz).

Bir §18.5 paragraf var başlatma ve sonlandırma §7.22.4.4 Paragraf aynıdır 11 standardına C ++ işlevi C11 standardında (yukarıda belirtildiği gibi) (ayrı bir dipnot gelen, ki sadece dokümanlar ve tanımlandığı gibidir içinde ).exitEXIT_SUCCESSEXIT_FAILURE<cstdlib>

Standart C - Ortak Uzantı

Klasik olarak, Unix sistemleri üçüncü bir varyantı destekler:

int main(int argc, char **argv, char **envp) { ... }

Üçüncü argüman, her biri bir adı, eşittir işareti ve bir değeri (muhtemelen boş) olan bir ortam değişkeni olan dizelere işaret eden boş bir sonlandırılmış listedir. Bunu kullanmazsanız, yine de ' extern char **environ;' ile çevreye ulaşabilirsiniz . Bu global değişken, POSIX'teki değişkenler arasında benzersizdir, çünkü bunu bildiren bir üstbilgisi yoktur.

Bu, C standardı tarafından Ek J'de belgelenen ortak bir uzantı olarak kabul edilmektedir:

J.5.1 Çevre argümanları

¶1 Barındırılan bir ortamda, ana işlev , her biri programın bu yürütülmesi için ortam hakkında bilgi sağlayan bir dizeye işaret char *envp[]eden boş bir sonlandırılmış işaretçi dizisine işaret eden üçüncü bir argüman alır char(5.1. 2.2.1).

Microsoft C

Microsoft VS 2010 derleyici ilginçtir. Web sitesi şöyle diyor:

Main için bildirim sözdizimi:

 int main();

veya isteğe bağlı olarak,

int main(int argc, char *argv[], char *envp[]);

Alternatif olarak, mainve wmainişlevleri dönen olarak bildirilebilir void(dönüş değeri yok). Herhangi bir beyanda bulunmuş mainveya wmaingeçersiz olarak geri dönüyorsanız, bir return deyimi kullanarak üst işlem veya işletim sistemine bir çıkış kodu döndüremezsiniz. mainVeya wmainolarak bildirildiğinde bir çıkış kodu döndürmek voidiçin exitişlevi kullanmanız gerekir .

Bir program çıktığında void main()(MS web sitesi de sessiz olduğunda) ne olacağı (ebeveyn veya işletim sistemine hangi çıkış kodunun döndürüldüğü) net değil .

İlginçtir, MS main(), C ve C ++ standartlarının gerektirdiği iki argümanlı versiyonunu reçete etmez . Sadece üçüncü argümanın olduğu üç argüman formu char **envp, çevre değişkenleri listesine bir işaretçi verir.

Microsoft sayfasında ayrıca wmain(), geniş karakter dizeleri alan bazı alternatifler ve daha fazlası da listelenmektedir .

Bu sayfanın Microsoft Visual Studio 2005 sürümü alternatif olarak listelenmiyor . Sürümleri Microsoft dan Visual Studio 2008 ve sonrası yok.void main()

Standart C - Bağımsız Ortam

Daha önce de belirtildiği gibi, yukarıdaki gereksinimler barındırılan ortamlar için geçerlidir. Bağımsız bir ortamla (barındırılan bir ortama alternatif olan) çalışıyorsanız, standardın söyleyecek çok daha azı vardır. Bağımsız bir ortam için, program başlangıcında çağrılan işlevin çağrılmasına gerek mainyoktur ve dönüş türünde herhangi bir kısıtlama yoktur. Standart diyor ki:

5.1.2 Yürütme ortamları

İki yürütme ortamı tanımlanmıştır: bağımsız ve barındırılan. Her iki durumda da, çalıştırma ortamı tarafından belirlenmiş bir C işlevi çağrıldığında programın başlatılması gerçekleşir. Statik depolama süresine sahip tüm nesneler, program başlatılmadan önce başlatılır (başlangıç ​​değerlerine ayarlanır). Bu tür başlatmanın şekli ve zamanlaması aksi belirtilmemiştir. Program sonlandırma denetimi yürütme ortamına döndürür.

5.1.2.1 Bağımsız ortam

Bağımsız bir ortamda (C programının yürütülmesinin bir işletim sisteminin faydası olmadan gerçekleşebileceği), program başlangıcında çağrılan işlevin adı ve türü uygulama tanımlıdır. Bağımsız bir program tarafından kullanılabilen, 4. maddede belirtilen asgari küme dışında kalan tüm kütüphane olanakları uygulama tarafından tanımlanır.

Bağımsız bir ortamda program sonlandırmanın etkisi uygulama tanımlıdır.

Madde 4 Uygunluğuna yapılan çapraz referans buna atıfta bulunur:

¶5 Kesin olarak uyumlu bir program yalnızca bu Uluslararası Standartta belirtilen dil ve kütüphanenin özelliklerini kullanacaktır. 3) Belirtilmemiş, tanımlanmamış veya uygulama tanımlı davranışlara bağlı olarak çıktı üretemez ve minimum uygulama sınırını aşmaz.

¶6 Uygun iki uygulama biçimi barındırılır ve bağımsızdır . Bir uygun barındırılan uygulama herhangi kesinlikle uygun bir program kabul edecektir. Bir uygun müstakil uygulama kütüphanesi maddesi (madde 7) belirtilen özelliklerinin kullanımı standart başlıklarının içeriğine sınırlı olduğu herhangi kesinlikle uygun programı kabul eder <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, ve <stdnoreturn.h>. Uygun bir uygulama, kesinlikle uygun programların davranışlarını değiştirmedikleri sürece uzantılara (ek kitaplık işlevleri dahil) sahip olabilir. 4)

¶7 Uygun bir program , uygun bir uygulama için kabul edilebilir bir programdır . 5)

3) Kesin olarak uyumlu bir program, kullanımın ilgili makro kullanılarak uygun bir koşullu içerme ön işleme yönergesi ile korunması koşuluyla koşullu özellikleri (bkz. 6.10.8.3) kullanabilir. Örneğin:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) Bu, uygun bir uygulamanın, bu Uluslararası Standartta açıkça saklı tutulanlar dışında hiçbir tanımlayıcı ayırmadığı anlamına gelir.

5) Kesinlikle uygun programların, uygun uygulamalar arasında maksimum düzeyde taşınabilir olması amaçlanmıştır. Uygun programlar, uygun bir uygulamanın taşınabilir olmayan özelliklerine bağlı olabilir.

Herhangi bir fonksiyonu tanımlayan bağımsız bir ortam için gereken tek başlığın <stdarg.h>(ve hatta bunlar sadece makrolar) olduğu dikkat çekicidir .

Standart C ++ - Bağımsız Ortam

C standardının hem barındırılan hem de bağımsız ortamı tanıdığı gibi, C ++ standardı da. (ISO / IEC 14882: 2011'den alıntılar.)

1.4 Uygulama uyumluluğu [intro.compliance]

Kinds7 İki tür uygulama tanımlanmıştır: barındırılan bir uygulama ve bağımsız bir uygulama . Barındırılan bir uygulama için bu Uluslararası Standart, kullanılabilir kitaplıklar kümesini tanımlar. Bağımsız bir uygulama, yürütmenin bir işletim sisteminin faydası olmadan gerçekleştirilebildiği ve belirli bir dil desteği kitaplıklarını içeren uygulama tanımlı bir kütüphane kümesine sahip olduğu uygulamadır (17.6.1.3).

¶8 Uygun bir uygulamanın, iyi biçimlendirilmiş bir programın davranışını değiştirmemesi kaydıyla uzantıları (ek kitaplık işlevleri dahil) olabilir. Bu standarda göre kötü biçimlendirilmiş uzantıları kullanan programları teşhis etmek için uygulamalar gerekmektedir. Ancak bunu yaptıktan sonra, bu tür programları derleyebilir ve yürütebilirler.

İmplementation9 Her uygulama, desteklemediği koşullu olarak desteklenen tüm yapıları tanımlayan ve yerel ayara özgü tüm özellikleri tanımlayan belgeler içermelidir. 3

3) Bu belge aynı zamanda uygulama tanımlı davranışı da tanımlar; bkz. 1.9.

17.6.1.3 Bağımsız uygulamalar [uygunluk]

İki tür uygulama tanımlanmıştır: barındırılan ve bağımsız (1.4). Barındırılan bir uygulama için, bu Uluslararası Standart mevcut üstbilgi kümesini açıklar.

Bağımsız bir uygulamanın, uygulama tanımlı bir üstbilgi kümesi vardır. Bu set en azından Tablo 16'da gösterilen başlıkları içermelidir.

Başlığın sağlanan sürümü <cstdlib>beyan eder en azından fonksiyonları abort, atexit, at_quick_exit, exit, vequick_exit (18.5). Bu tabloda listelenen diğer başlıklar, barındırılan bir uygulama ile aynı gereksinimleri karşılamalıdır.

Tablo 16 - Bağımsız uygulamalar için C ++ başlıkları

Subclause                           Header(s)
                                    <ciso646>
18.2  Types                         <cstddef>
18.3  Implementation properties     <cfloat> <limits> <climits>
18.4  Integer types                 <cstdint>
18.5  Start and termination         <cstdlib>
18.6  Dynamic memory management     <new>
18.7  Type identification           <typeinfo>
18.8  Exception handling            <exception>
18.9  Initializer lists             <initializer_list>
18.10 Other runtime support         <cstdalign> <cstdarg> <cstdbool>
20.9  Type traits                   <type_traits>
29    Atomics                       <atomic>

int main()C'de kullanmaya ne dersiniz ?

C11 standardının §5.1.2.2.1 standardı tercih edilen gösterimi gösterir -  int main(void)- ancak standartta aşağıdakileri gösteren iki örnek vardır int main(): §6.5.3.4 ¶8 ve §6.7.6.3 ¶20 . Şimdi, örneklerin 'normatif' olmadığını belirtmek önemlidir; bunlar sadece açıklayıcıdır. Örneklerde hatalar varsa, standardın ana metnini doğrudan etkilemezler. Bununla birlikte, beklenen davranışın güçlü bir göstergesidir, bu nedenle standart int main()bir örnekte yer int main()alıyorsa, tercih edilen gösterim olmasa bile yasak olmadığını gösterir.

6.5.3.4 sizeofve _Alignofoperatörleri

...

EX8 ÖRNEK 3 Bu örnekte, değişken uzunluktaki bir dizinin boyutu hesaplanır ve bir işlevden döndürülür:

#include <stddef.h>

size_t fsize3(int n)
{
    char b[n+3]; // variable length array
    return sizeof b; // execution time sizeof
}
int main()
{
    size_t size;
    size = fsize3(10); // fsize3 returns 13
    return 0;
}

@DavidBowling: gibi bir işlev tanımı int main(){ … }, işlevin bağımsız değişken almadığını, ancak AFAICT işlev prototipi sağlamadığını belirtir. Çünkü main()bu nadiren bir problemdir; bu, yinelemeli çağrılarınız varsa main(), bağımsız değişkenlerin kontrol edilmeyeceği anlamına gelir . Diğer işlevler için bu daha çok bir sorundur - bağımsız değişkenlerin doğru olduğundan emin olmak için işlev çağrıldığında gerçekten kapsamda bir prototipe ihtiyacınız vardır.
Jonathan Leffler

1
@DavidBowling: Normalde IOCCC main()gibi yerlerin dışında yinelemeli olarak arama yapmazsınız . Bunu yapan bir test programım var - esas olarak yenilik için. int i = 0; int main() { if (i++ < 10) main(i, i * i); return 0; }GCC'niz varsa ve derlerseniz ve -Wstrict-prototypesiçermezseniz, sıkı uyarılar altında temiz bir şekilde derler. Eğer öyleyse main(void), derlenemez.
Jonathan Leffler

61

Ben inanıyorum main()ya dönmelidir EXIT_SUCCESSveya EXIT_FAILURE. Bunlar,stdlib.h


20
0 da standarttır.
Chris Young

2
@ChrisYoung Bazı tarihsel işletim sistemleri (VMS?) Vardır EXIT_SUCCESSve EXIT_FAILUREçünkü başarıyı göstermek için 0'dan farklı bir sayı kullanır. Bugünlerde her yerde 0.
fuz

5
@FUZxxl haklısınız, ancak bu yorumumla çelişmiyor. EXIT_SUCCESS gerçekten sıfırdan farklı olabilir, ancak standartların (C89, C99, C11) hepsi de 0 (ve EXIT_SUCCESS) durum başarılı sonlandırmanın uygulama tanımlı bir formu olarak tanımlanır.
Chris Young

2
@FUZxxl: VMS'nin başarıyı göstermek için tek değerler (1 gibi) ve başarısızlığı göstermek için çift değerler (0 gibi) kullandığı doğrudur. Ne yazık ki, orijinal ANSI C standardı EXIT_SUCCESS'in 0 olması gerektiği şeklinde yorumlandı, bu nedenle EXIT_SUCCESS'i anadan döndürmek VMS'de tam olarak yanlış davranışa sahip oldu. VMS için yapılacak taşınabilir şey kullanmaktı exit(EXIT_SUCCESS), bu da her zaman doğru olanı yaptı.
Adrian McCarthy

1
5.1.2.2.3 "Ana işlevin dönüş türü int ile uyumlu bir türse, ilk çağrıdan ana işleve dönüş, ana işlev tarafından argüman olarak döndürülen değerle çıkış işlevini çağırmaya eşdeğerdir; 11) ana işlevi sonlandıran} değere ulaşmak 0 değerini döndürür. "
Lundin

38

C ve C ++ standartlarının iki tür uygulama tanımladığını unutmayın: bağımsız ve barındırılan.

  • C90 tarafından barındırılan ortam

    İzin verilen formlar 1 :

    int main (void)
    int main (int argc, char *argv[])
    
    main (void)
    main (int argc, char *argv[])
    /*... etc, similar forms with implicit int */

    Yorumlar:

    İlk ikisi açıkça izin verilen formlar olarak belirtilir, diğerlerine dolaylı olarak izin verilir, çünkü C90 dönüş türü ve işlev parametreleri için "örtük int" e izin verir. Başka bir forma izin verilmez.

  • C90 bağımsız ortam

    Herhangi bir ana form veya isme izin verilir 2 .

  • C99 tarafından barındırılan ortam

    İzin verilen formlar 3 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */

    Yorumlar:

    C99 kaldırıldı "örtük int" yani main()artık geçerli değil.

    Garip, belirsiz bir cümle "ya da başka bir uygulama tanımlı şekilde" tanıtıldı. Bu, " int main()değişkenlik gösterebilecek parametreler " veya "ana, herhangi bir uygulama tanımlı forma sahip olabilir" olarak yorumlanabilir.

    Bazı derleyiciler, standardı ikinci şekilde yorumlamayı seçmiştir. Tartışmalı olarak, belirsiz olduğu için standart kendi içinde atıfta bulunarak kesinlikle uymadıklarını kolayca söyleyemez.

    Ancak, tamamen vahşi biçimlere izin vermek main()muhtemelen bu yeni cümlenin niyeti değildi (?). C99 gerekçesi (normatif değil), cümlenin int main 4 için ek parametrelere karşılık geldiğini ima eder .

    Yine de, barındırılan çevre programı sonlandırma bölümü, ana 5'in geri dönmediği durum hakkında tartışmaya devam etmektedir . Bu bölüm, main'in nasıl bildirilmesi gerektiği konusunda normatif olmasa da, main'nin barındırılan sistemlerde bile tamamen uygulama tanımlı bir şekilde bildirilebileceği anlamına gelir.

  • C99 bağımsız ortam

    Herhangi bir ana form veya isme izin verilir 6 .

  • C11 barındırılan ortam

    İzin verilen formlar 7 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
  • C11 bağımsız ortam

    Herhangi bir ana form veya isme izin verilir 8 .


int main()Yukarıdaki sürümlerin herhangi birinde barındırılan herhangi bir C uygulaması için hiçbir zaman geçerli bir form olarak listelenmediğini unutmayın . C yılında C aksine ++, ()ve (void)farklı anlamlara sahiptir. Birincisi, dilden kaldırılabilen eskimiş bir özelliktir. Gelecekteki C11 dil yönergelerine bakın:

6.11.6 Fonksiyon tanımlayıcıları

Boş parantezli işlev bildiricilerin kullanımı (prototip biçiminde parametre türü bildiriciler değil) eskimiş bir özelliktir.


  • C ++ 03 barındırılan ortam

    İzin verilen formlar 9 :

    int main ()
    int main (int argc, char *argv[])

    Yorumlar:

    İlk formdaki boş parantezlere dikkat edin. C ++ ve C bu durumda farklıdır, çünkü C ++ 'da bu işlevin parametre almadığı anlamına gelir. Ancak C'de herhangi bir parametre alabileceği anlamına gelir.

  • C ++ 03 bağımsız ortam

    Başlangıçta çağrılan işlevin adı, uygulama tanımlıdır. Eğer isimlendirilmiş ise main(), belirtilen formlara uymalıdır 10 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
  • C ++ 11 barındırılan ortam

    İzin verilen formlar 11 :

    int main ()
    int main (int argc, char *argv[])

    Yorumlar:

    Standardın metni değiştirildi ancak aynı anlamı taşıyor.

  • C ++ 11 bağımsız ortam

    Başlangıçta çağrılan işlevin adı, uygulama tanımlıdır. Eğer isimlendirilmiş main()ise belirtilen formlara uymalıdır 12 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])

Referanslar

  1. ANSI X3.159-1989 2.1.2.2 Barındırılan ortam. "Program başlangıcı"

    Program başlangıcında çağrılan fonksiyon main olarak adlandırılır. Uygulama, bu işlev için herhangi bir prototip bildirmez. Dönüş türü int ile ve parametresiz olarak tanımlanmalıdır:

    int main(void) { /* ... */ } 

    veya iki parametre ile (burada argc ve argv olarak adlandırılırlar, ancak bildirildikleri işlevin yerel oldukları için herhangi bir ad kullanılabilir):

    int main(int argc, char *argv[]) { /* ... */ }
  2. ANSI X3.159-1989 2.1.2.1 Bağımsız ortam:

    Bağımsız bir ortamda (C programının yürütülmesinin bir işletim sisteminin faydası olmadan gerçekleşebileceği), program başlangıcında çağrılan işlevin adı ve türü uygulama tanımlıdır.

  3. ISO 9899: 1999 5.1.2.2 Barındırılan ortam -> 5.1.2.2.1 Programın başlatılması

    Program başlangıcında çağrılan fonksiyon main olarak adlandırılır. Uygulama, bu işlev için herhangi bir prototip bildirmez. Dönüş türü int ile ve parametresiz olarak tanımlanmalıdır:

    int main(void) { /* ... */ } 

    veya iki parametre ile (burada argc ve argv olarak adlandırılırlar, ancak bildirildikleri işlevin yerel oldukları için herhangi bir ad kullanılabilir):

    int main(int argc, char *argv[]) { /* ... */ }

    ya da eşdeğeri; 9) ya da başka bir uygulama-tanımlı tarzda.

  4. Uluslararası Standart - Programlama Dilleri için Gerekçe - C, Revizyon 5.10. 5.1.2.2 Barındırılan ortam -> 5.1.2.2.1 Programın başlatılması

    Argümanların anaya ve çıkış, ana ve atexit etkileşimi (bkz. §7.20.4.2), argv dizelerinin gösterilmesinde ve main tarafından döndürülen değerlerin anlamında bazı istenmeyen çeşitlilikleri engellemek için kodlanmıştır.

    Argc ve argv'nin main argümanları olarak tanımlanması, kapsamlı önceki uygulamaları tanır. argv [argc], listenin sonu için de ortak uygulama temelinde gereksiz bir denetim sağlamak için bir boş gösterici olmalıdır.

    main, sıfır veya iki bağımsız değişkenle taşınabilir olarak bildirilebilecek tek işlevdir. (Diğer işlevlerin bağımsız değişkenlerinin sayısı, çağırma ve tanım arasında tam olarak eşleşmelidir.) Bu özel durum, program program bağımsız değişken dizelerine erişmediğinde bağımsız değişkenleri anaya bırakma yöntemini basitçe tanır. Birçok uygulama ana ikiden fazla argümanı desteklese de, bu tür bir uygulama Standart tarafından kutsanmamış veya yasaklanmamıştır; main'yi üç argümanla tanımlayan bir program kesinlikle uygun değildir (bkz. §J.5.1.).

  5. ISO 9899: 1999 5.1.2.2 Barındırılan ortam -> 5.1.2.2.3 Program sonlandırma

    Ana işlevin dönüş türü int ile uyumlu bir türse, ilk çağrıdan ana işleve dönüş, ana işlev tarafından argüman olarak döndürülen değerle çıkış işlevini çağırmaya eşdeğerdir; 11) }bu sona erer ana işlev 0 değerini döndürür. Dönüş türü int ile uyumlu değilse, ana bilgisayar ortamına döndürülen sonlandırma durumu belirtilmez.

  6. ISO 9899: 1999 5.1.2.1 Bağımsız ortam

    Bağımsız bir ortamda (C programının yürütülmesinin bir işletim sisteminin faydası olmadan gerçekleşebileceği), program başlangıcında çağrılan işlevin adı ve türü uygulama tanımlıdır.

  7. ISO 9899: 2011 5.1.2.2 Barındırılan ortam -> 5.1.2.2.1 Programın başlatılması

    Bu bölüm yukarıda belirtilen C99 ile aynıdır.

  8. ISO 9899: 1999 5.1.2.1 Bağımsız ortam

    Bu bölüm yukarıda belirtilen C99 ile aynıdır.

  9. ISO 14882: 2003 3.6.1 Ana işlev

    Bir uygulama ana işlevi önceden tanımlamaz. Bu işlev aşırı yüklenmemelidir. İnt türünde bir dönüş türüne sahip olacaktır, ancak aksi takdirde türü uygulama tanımlıdır. Tüm uygulamalar, aşağıdaki ana tanımların her ikisine de izin verecektir:

    int main() { /* ... */ }

    ve

    int main(int argc, char* argv[]) { /* ... */ }
  10. ISO 14882: 2003 3.6.1 Ana işlev

    Bir ana işlevi tanımlamak için bağımsız bir ortamdaki bir programın gerekli olup olmadığı uygulama tarafından tanımlanır.

  11. ISO 14882: 2011 3.6.1 Ana işlev

    Bir uygulama ana işlevi önceden tanımlamaz. Bu işlev aşırı yüklenmemelidir. İnt türünde bir dönüş türüne sahip olacaktır, ancak aksi takdirde türü uygulama tanımlıdır. Tüm uygulamalar,

    - int döndüren () işlevi

    - int döndüren (int, işaretçi - işaretçi) işlevi

    ana tip olarak (8.3.5).

  12. ISO 14882: 2011 3.6.1 Ana işlev

    Bu bölüm yukarıda belirtilen C ++ 03 ile aynıdır.


Bir soru: C ++ standartları, bağımsız ortamlarda başlatma işlevinin imzasının uygulamanın da tanımlandığı anlamına mı geliyor? Örneğin, bir uygulama başlangıç ​​işlevini şu şekilde tanımlayabilirdi: int my_startup_function ()ya da int my_startup_function (int argc, char *argv[])örneğin: char my_startup_function (long argc, int *argv[])bir başlangıç ​​işlevi olarak da olabilir mi? Sanırım hayır, değil mi? Ayrıca, bu da belirsiz değil mi?
Utku

@Utku Adı verilmediği sürece herhangi bir imzası olabilir, main()çünkü o zaman listelenen imzalardan birini kullanmalıdır. void my_startup_function ()Bağımsız sistemlerde programdan geri dönmek mantıklı olmadığından , ezici bir çoğunlukla en yaygın olanın olacağını düşünürdüm .
Lundin

1
Anlıyorum. Ancak başlatma işlevi için herhangi bir ad ve imza kullanmasına izin verilirse, neden farklı bir imza kullanmanıza izin vermiyorsunuz main? Bu akıllıca bir soru değilse üzgünüm ama arkasındaki mantığı anlayamadım.
Utku

@Utku C ve C ++ orada farklı. Neden C ++ bunu zorlarsa, hiçbir fikrim yok, mantık yok. Ben ana suçlu (pun amaçlı) erken ana ana int, dönem dönmek gerektiğini ilan Stroustrup olduğunu düşünüyorum. Çünkü ilk C ++ sürümünü hazırladığında, sadece barındırılan sistemlere alışıktı. Bağlantılı gönderide, Stroustrup hala bağımsız uygulamaların varlığından habersiz görünüyor: örneğin, cahil olarak C standardının barındırılan uygulama alt bölümüne atıfta bulunuyor ve bölüm 5.1.2.1'in varlığını görmezden geliyor.
Lundin

1
C11 standart taslağı hakkında dikkate değer bir şey func(), eskimiş olarak kabul edilmesine rağmen , taslağın int main()kendi örneklerinde kullanmasıdır.
Antti Haapala

29

Başarı için 0 ve hata için sıfırdan farklı bir değerle geri dönün. Bu, programınızla ne olduğunu öğrenmek için UNIX ve DOS komut dosyaları tarafından kullanılan standarttır.


8

main() C89 ve K&R C'de belirtilmemiş dönüş türleri varsayılan olarak 'int` olarak ayarlanmıştır.

return 1? return 0?
  1. İçine bir return ifadesi int main()yazmazsanız, kapanış {varsayılan olarak 0 değerini döndürür.

  2. return 0veya return 1üst süreç tarafından alınacaktır. Bir kabukta bir kabuk değişkenine gider ve programınızı çalıştırıyorsanız bir kabuk oluşturur ve bu değişkeni kullanmıyorsanız, dönüş değeri hakkında endişelenmenize gerek yoktur main().

Bkz. Ana işlevimin geri döndüğünü nasıl alabilirim? .

$ ./a.out
$ echo $?

Bu şekilde, bunun $?dönüş değerinin en az önemli baytını alan değişken olduğunu görebilirsiniz main().

Unix ve DOS komut dosyalarında, return 0genellikle başarılı ve hata için sıfır dışında döndürülür. Bu, programınızla ne olduğunu öğrenmek ve tüm akışı kontrol etmek için Unix ve DOS komut dosyaları tarafından kullanılan standarttır.


4
Açıkçası, $?bir ortam değişkeni değildir; kabuk önceden tanımlanmış (veya yerleşik) bir değişkendir. Farkı bulmak zordur, ancak çalıştırırsanız env(herhangi bir argüman olmadan), ortamı yazdırır ve çevrede $?gösterilmez.
Jonathan Leffler

1
Ana "sonun düşmesi" C90'da değil, sadece C ++ ve C99'da olduğunda 0 döndürülür.
Kaz

Yazım hatası: "kapanış {" olmalıdır }. SO bu kadar küçük bir düzenleme yapmama izin vermiyor.
Spencer

7

Bir int döndürseniz bile, bazı işletim sistemlerinin (Windows) döndürülen değeri tek bir bayta (0-255) indirdiğini unutmayın.


4
Unix muhtemelen diğer işletim sistemlerinin çoğunda olduğu gibi aynı şeyi yapar. VMS'nin EXIT_SUCCESS veya EXIT_FAILURE dışında herhangi bir şey döndürmenin sorun istemesi gibi inanılmaz garip şeyler yaptığını biliyorum.
Leon Timmermans

2
MSDN farklı olmaya yalvarır: mscorlib aracılığıyla rapor edildiğinde, çıkış kodu işaretli bir 32 bit tam sayıdır . Bu, çıkış kodlarını kesen C çalışma zamanı kitaplıklarının arızalı olduğu anlamına gelir .

Evet, bu yanlış. Windows'ta 32 bitlik bir tamsayı döndürülür (ve dönüştürülür unsigned). Bu, 32 bit tamsayılara sahip UNIX sistemlerinde aynıdır. Ancak, her iki sistemdeki UNIX stili mermiler genellikle yalnızca imzasız 8 bitlik bir tam sayı korur.
John McFarlane

4

Dönüş değeri, programın nasıl kapatıldığını kontrol etmek için işletim sistemi tarafından kullanılabilir.

Dönüş değeri 0 genellikle çoğu işletim sisteminde (yine de düşünebildiğim) Tamam anlamına gelir.

Ayrıca, bir işlemi kendiniz çağırdığınızda ve programın çıkıp çıkmadığını ve bitip bitmediğini kontrol edebilirsiniz.

Bu sadece bir programlama kuralı DEĞİLDİR .


Soruda, bir operatif sistemin mevcut olduğunu gösteren hiçbir şey yoktur. Bir değer döndürmek, bağımsız bir sistemde bir anlam ifade etmez.
Lundin

3

Dönüş değeri main()programın nasıl çıktığını gösterir. Dönüş değeri ise, zerosıfır olmayan herhangi bir değer, yürütmede bir şeyin kötü gittiğini gösterirken yürütmenin başarılı olduğu anlamına gelir.


1
Bu, sorunun cevabı değil bir yorumdur.
Lundin

2

Standardın başarılı bir getiri OS tabanlı olduğu için bir dönüş değerine ihtiyaç duymadığını belirten bir izlenim altındaydım (birinde sıfır, diğerinde başarı veya başarısızlık olabilir), bu nedenle geri dönüşün olmaması derleyici başarılı dönüş kendisi eklemek için.

Ancak genellikle 0 döndürür.


C99 (ve C ++ 98), return ifadesini anadan atlamanıza olanak tanır; C89, return ifadesini atlamanıza izin vermez.
Jonathan Leffler

Bu bir cevap değil bir yorum.
Lundin

Bu soruya bir cevap sağlamaz. Bir yazardan eleştiri veya açıklama istemek için gönderilerinin altına bir yorum bırakın.
Steve Lillis

6
@SteveLillis: 2008'de SO'nun bir yorum bölümü yoktu.
graham.reeds

2

0 döndürüldüğünde programcıya programın işi başarıyla tamamladığını söylemelidir.


main()Normalde 1 döndürüldüğünde bir hata oluştu; 0 döndürmesi başarıyı gösterir. Programlarınız her zaman başarısız olursa, 1 tamamdır, ancak en iyi fikir değildir.
Jonathan Leffler

1
@JonathanLeffler: dönen anlamı 1gelen mainuygulama tanımlı olduğunu. Yalnızca dil tanımlı değerler 0, EXIT_SUCCESS(genellikle olarak tanımlanır 0) ve EXIT_FAILURE. OpenVMS'de başarılı bir fesih return 1;anlamına gelir .
Keith Thompson

VMS 'normal' değil - söylediğim anlamında. 'Tek bir değer başarıdır' gibi bir şey değil mi? değerleri bile başarısız 'VMS?
Jonathan Leffler

2

Çıkarmak return 0

Bir C veya C ++ programı mainderleyicinin sonuna geldiğinde otomatik olarak 0 döndürmek için kod oluşturur, bu yüzden return 0;açıkça sonuna koymak gerekmez main.

Not: Bu öneriyi yaptığımda, neredeyse iki tür yorumdan birini takip ediyor: "Bunu bilmiyordum." veya "Bu kötü bir tavsiye!" Benim mantığım, standart tarafından açıkça desteklenen derleyici davranışına güvenmenin güvenli ve yararlı olmasıdır. C için, C99'dan beri; bkz. ISO / IEC 9899: 1999 bölüm 5.1.2.2.3:

[...] ilk çağrıdan mainişleve geri dönüş exit, mainişlevin bağımsız değişken olarak döndürdüğü değerle işlevin çağrılmasına eşdeğerdir ; ulaşan }son bulan mainfonksiyon döndürür 0 değeri.

C ++ için, 1998'deki ilk standarttan beri; ISO / IEC 14882: 1998 bölüm 3.6.1'e bakınız:

Denetim, bir return deyimiyle karşılaşmadan ana sonuna ulaşırsa, sonuç, dönüş 0'ı yürütmektir;

O zamandan bu yana her iki standardın tüm sürümleri (C99 ve C ++ 98) aynı fikri korumuştur. C ++ 'da otomatik olarak oluşturulan üye işlevlerine güveniyoruz ve birkaç kişi return;bir voidişlevin sonunda açık ifadeler yazıyor . Atlamanın nedenleri "tuhaf görünüyor" . Benim gibi, C standardındaki değişikliğin mantığını merak ediyorsanız bu soruyu okuyun . Ayrıca, 1990'ların başında bunun "özensiz uygulama" olarak kabul edildiğini, çünkü o sırada tanımlanmamış davranış (yaygın olarak desteklenmesine rağmen) olduğunu da unutmayın.

Buna ek olarak, C ++ Temel Yönergelerireturn 0; sonunda birden fazla çıkarma örneği içerir mainve açık bir dönüşün yazıldığı hiçbir örnek yoktur. Belgede bu konu hakkında henüz belirli bir kılavuz olmamasına rağmen, bu uygulamanın en azından örtük bir tasviri gibi gözükmektedir.

Bu yüzden atlamayı savunuyorum; Diğerleri katılmıyorum (genellikle şiddetle!) Her durumda, onu ihmal eden bir kodla karşılaşırsanız, standart tarafından açıkça desteklendiğini bilirsiniz ve bunun ne anlama geldiğini bilirsiniz.


2
Bu kötü bir tavsiye çünkü daha sonraki bir standart değil, sadece C89'u uygulayan derleyiciler hala oldukça yaygın (2017'de yazıyorum) ve öngörülebilir gelecek için son derece yaygın kalacak. Örneğin, son kontrol ettim hiçbir Microsoft'un derleyicilerinin versiyonu C99 uygulanan ve da GCC olmayan gömülü sistem derleyiciler için hala tipik benim anlaşılmasıdır.
zwol

4
@zwol: 28 yıl boyunca güncel olmayan bir derleyici kullanmaktan başka seçeneği olmayan herkes muhtemelen açıkça dahil edilip edilmeyeceğine karar vermekten daha fazla sorun yaşıyor return 0;, ancak o dönemin birçok derleyicisinin de return 0;daha önce bile örtük uyguladığına dikkat çekerim. standardize.
Edward

2
Aslında, çok sayıda gömülü sistem çalışıyorum ve return 0on yıldan fazla bir süredir örtük desteklemeyen bir derleyici ile karşılaşmadım . Ayrıca Microsoft C'nin güncel sürümleri de bunu desteklemektedir . Belki de bilgileriniz güncel değil?
Edward

2
Bu, C (neredeyse @ zwol başına) tartışmalı olduğunu takdir edebilirsiniz. C ++ 'da bunu çevreleyen herhangi bir tartışma saf saçmalıktır.
Yörüngedeki Hafiflik Yarışları

2
@Edward tartışmanın olmadığını söylemedim, saçmalık dedim: P
Orbit'teki Hafiflik Yarışları

1

Ne döndüreceğiniz yürütülebilir dosyayla ne yapmak istediğinize bağlıdır. Örneğin, programınızı bir komut satırı kabuğuyla kullanıyorsanız, başarı için 0 ve başarısızlık için sıfır olmayan bir değer döndürmeniz gerekir. Daha sonra programı, kodunuzun sonucuna bağlı olarak koşullu işleme ile kabuklarda kullanabilirsiniz. Ayrıca, yorumunuza göre sıfır olmayan herhangi bir değer atayabilirsiniz, örneğin kritik hatalar için farklı program çıkış noktaları farklı çıkış değerlerine sahip bir programı sonlandırabilir ve bu çağrı çağı için döndürülen değeri inceleyerek ne yapılacağına karar verebilir. Kod kabuklarla kullanılmak üzere tasarlanmamışsa ve döndürülen değer kimseyi rahatsız etmiyorsa, atlanabilir. Ben şahsen imzayı kullanıyorumint main (void) { .. return 0; .. }


Main () biçimi derleyici anlamına gelen uygulama tarafından belirlenir. Programlayıcı, bir derleyicinin birkaç formu desteklemesi dışında hangi formun seçileceğini seçmez.
Lundin

@Lundin Dönüş türü uygulama tarafından uygulanacaktır. Ancak döndürülecek değere programcı karar verir. C99 Bölüm 5.1.2.2.3, dönüş tipinin mainuyumlu olduğundan bahseder int. Bu nedenle geri dönmek intbir sorun olmayacaktır. Diğer dönüş türlerine izin verilse de, bu durumda dönüş değerine sahip ortam değişkeni belirtilmez. Ama eğer bir programcı return 0;bash yaparsa, dal yapmak için kullanılabilir.
phoxis

1

Bir işlemden bir tamsayı döndürmenin etkinliği ile ilgili sorunlarınız varsa, bu işlemi bu dönüş değerinin bir sorun haline gelmesi için o kadar çok çağırmaktan kaçınmalısınız.

Bunu yapıyorsanız (bir işlemi bu kadar çok kez çağırın), her çağrı için belirli bir işlem ayırmadan mantığınızı doğrudan arayanın içine veya bir DLL dosyasına koymanın bir yolunu bulmalısınız; çoklu işlem tahsisleri size bu durumda ilgili verimlilik sorununu getirir.

Ayrıntılı olarak, yalnızca 0 döndürmenin 1 döndürmekten daha mı yoksa daha az verimli olup olmadığını bilmek istiyorsanız, bazı durumlarda derleyiciden kaynaklanabilir, ancak genel olarak, aynı kaynaktan (yerel, alan, sabit, gömülü) okundukları varsayılarak kodda, işlev sonucunda vb.) tam olarak aynı sayıda saat döngüsü gerektirir.


1

İşte dönüş kodlarının kullanımının küçük bir gösterimi ...

Linux terminalinin sağladığı çeşitli araçları kullanırken, dönüş kodu örneğin işlem tamamlandıktan sonra hata işleme için kullanılabilir. Aşağıdaki metin dosyası dosyamın bulunduğunu düşünün:

Bu, grep'in nasıl çalıştığını kontrol etmek için bazı örneklerdir.

Grep komutunu çalıştırdığınızda bir işlem oluşturulur. Bir kez bittiğinde (ve kırılmadığında) 0 ile 255 arasında bir kod döndürür. Örneğin:

$ grep order myfile

Yaparsan

$ echo $?
$ 0

0 alırsınız. Neden? Çünkü grep bir eşleşme buldu ve bir çıkış kodu 0 döndürdü, bu da başarılı bir şekilde çıkmak için normal değerdir. Tekrar kontrol edelim, ancak metin dosyamızın içinde olmayan bir şeyle, dolayısıyla hiçbir eşleşme bulunmayacak:

$ grep foo myfile
$ echo $?
$ 1

Grep, "foo" jetonunu dosyamızın içeriğiyle eşleştiremediğinden, dönüş kodu 1'dir (bu bir hata oluştuğunda olağan durumdur, ancak yukarıda belirtildiği gibi seçim yapabileceğiniz çok sayıda değeriniz vardır).

Şimdi aşağıdaki bash betiği (basitçe bir Linux terminaline yazın), ancak çok temel bir hata işleme fikri vermelidir:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

İkinci satırdan sonra "foo" grep dönüşü 1 yaptığı için terminale hiçbir şey basılmaz ve grep'in dönüş kodunun 0'a eşit olup olmadığını kontrol ederiz. == 1.

Gördüğünüz gibi, bu işlemi çağırıp çağırmadığınızı ve bu işlemi ne döndürdüğünü görmek esastır (main () dönüş değeri ile).


Bir kabuk komut dosyasında, if grep foo myfile; then echo 'Match found'; else echo 'No match was found'; fidönüş durumunu doğrudan test etmek için şunu kullanırsınız . Durumu (raporlama vb. İçin) yakalamak istiyorsanız bir ödev kullanırsınız. Sen kullanabilir if grep foo myfile; CHECK=$?; [ "$CHECK" = 0 ]; then echo 'Match found'; else echo 'No match was found'; fiveya üç satırlık kullanabilir. Ayrıca seçenekleri kullanabilirsiniz -sve -qhiç grepgörünmesini eşleşmeleri ya da rutin hata iletileri engellemek için. Ancak, bu kabuk minutiae - çıkış durumunun yararlı olabileceği anahtar nokta - sorun yok.
Jonathan Leffler

1

C ve C ++ 'da main () işlevini tanımlamanın doğru (en etkili) yolu nedir - int main () veya void main () - ve neden?

Bu "(en verimli)" kelimeleri soruyu değiştirmez. Bağımsız bir ortamda değilseniz, beyan etmenin evrensel olarak doğru bir yolu vardır main()ve bu int olarak geri döner.

main()C ve C ++ 'da ne dönmeli?

Bu gibi değil gerektiğini main() ne bundan, dönüş yapar main() dönüşü. main()elbette, başkasının aradığı bir fonksiyondur. Çağıran kod üzerinde herhangi bir kontrole sahip değilsiniz main(). Bu nedenle, arayanıyla main()eşleşmesi için doğru türde bir imza ile bildirmeniz gerekir . Bu konuda herhangi bir seçeneğiniz yok. Kendinize az ya da çok neyin verimli olduğunu ya da neyin daha iyi ya da daha kötü bir tarz olduğunu ya da bunun gibi herhangi bir şeyi sormak zorunda değilsiniz, çünkü cevap zaten sizin için C ve C + standartlarına göre mükemmel bir şekilde tanımlanmıştır. Sadece takip et.

İnt main () ise 1 döndürür veya 0 döndürür mü?

Başarı için 0, başarısızlık için sıfır olmayan. Yine, seçmeniz gereken (veya almanız gereken) bir şey değil: uymanız gereken arayüz tarafından tanımlanır.

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.