main () ควรส่งคืนใน C และ C ++ อย่างไร


695

เป็นวิธีที่ถูกต้อง (มีประสิทธิภาพมากที่สุด) วิธีการกำหนดmain()ฟังก์ชั่นใน C และ C ++ - int main()หรือvoid main()- และทำไม? หากint main()แล้วreturn 1หรือreturn 0?


มีคำถามซ้ำหลายประการซึ่งรวมถึง:

ที่เกี่ยวข้อง:


28
ฉันยังคิดว่ามันค่อนข้างคลุมเครือเช่นกัน กำหนด "ประสิทธิภาพสูงสุด" สำหรับฉัน มีประสิทธิภาพในสิ่งที่เหมาะสม? ในแง่ของการใช้หน่วยความจำน้อยลงหรือไม่ ในแง่ของการทำงานที่เร็วขึ้น? ฉันเห็นคำตอบที่เป็นประโยชน์ แต่ฉันก็ยังคิดว่าคำถามนั้นเป็นประโยคที่ค่อนข้างแย่
Onorio Catenacci

7
เมื่อเร็ว ๆ นี้บริบทของประสิทธิภาพมีความชัดเจนที่นี่โดยเฉพาะอย่างยิ่งกับตัวอย่าง (ซึ่งน่าจะมีคำจำกัดความของ 'ประสิทธิภาพ') หวังว่าบัฟเฟอร์ที่ไม่ดีจะไม่คลานเข้าไปในรูและเสียใจกับคำถามทั้งหมด อาจกล่าวได้ว่าไม่ว่าจะเป็นโมฆะหรือ int ค่าจะถูกส่งคืนดังนั้นจึงไม่มีผลกระทบกับขนาดไฟล์การดำเนินการหรือการจัดสรรหน่วยความจำ และผู้คนในระบบปฏิบัติการส่วนใหญ่มักจะกลับมาเป็น 0 เมื่อประสบความสำเร็จและอย่างอื่นที่ประสบความสำเร็จหรือล้มเหลว - แต่ไม่มีมาตรฐาน ในที่สุดไม่มีความแตกต่างในประสิทธิภาพในลักษณะที่ชัดเจนใด ๆ
Kit10

"ถูกต้อง (มีประสิทธิภาพมากที่สุด)" ไม่สมเหตุสมผล มีประสิทธิภาพคือสิ่งหนึ่งที่ถูกต้องเป็นอีกสิ่งหนึ่ง mainถูกเรียกหนึ่งครั้ง (และใน C ++ สามารถเรียกได้เพียงครั้งเดียวเท่านั้น: ไม่มีการเรียกซ้ำ) หากคุณไม่ต้องการให้การประมวลผลใช้เวลาเป็นจำนวนมากmainดังนั้นอย่าเรียกใช้โปรแกรมหลาย ๆ ครั้ง: ทำให้โปรแกรมใช้การทำซ้ำ
Kaz

2
ฉันคิดว่ามันน่าสนใจที่ไม่มีคำตอบเท่าที่ฉันสามารถบอกได้ให้เป็นตัวอย่างการทำงานอย่างเต็มที่รวมถึง#includeงบ
puk

3
ค่าส่งคืนไม่สมเหตุสมผลบนแพลตฟอร์มที่ไม่มีระบบปฏิบัติการ คุณไม่ได้กลับไปทำอะไรเลย หากคุณตีreturnในmain(...)บนอุปกรณ์ฝังตัวระบบของคุณจะเข้าสู่สภาวะที่คาดเดาไม่ได้และเครื่องซักผ้าของคุณจะกลายเป็นตัวรู้และพยายามที่จะฆ่าคุณ ดังนั้นเราใช้void main()ในกรณีนั้น นี่คือการปฏิบัติมาตรฐานอุตสาหกรรมในการฝังโลหะเปลือย
3Dave

คำตอบ:


570

ค่าส่งคืนสำหรับmainระบุวิธีการออกจากโปรแกรม ปกติออกจากเป็นตัวแทนจากค่า 0 mainกลับมาจาก การออกที่ผิดปกติจะถูกส่งสัญญาณโดยการส่งคืนที่ไม่เป็นศูนย์ แต่ไม่มีมาตรฐานสำหรับวิธีการตีความรหัสที่ไม่เป็นศูนย์ ตามที่ระบุไว้โดยผู้อื่นvoid main()เป็นสิ่งต้องห้ามตามมาตรฐาน C ++ และไม่ควรใช้ mainลายเซ็นC ++ ที่ถูกต้องคือ:

int main()

และ

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

ซึ่งเทียบเท่ากับ

int main(int argc, char** argv)

นอกจากนี้ยังเป็นที่น่าสังเกตว่าใน C ++ int main()สามารถทิ้งไว้ได้โดยไม่มีคำสั่ง return ซึ่งเป็นจุดเริ่มต้นของการคืนค่า 0 ซึ่งเป็นจริงด้วยโปรแกรม C99 ไม่ว่าreturn 0;ควรจะมองข้ามหรือไม่ได้เปิดให้มีการอภิปราย ช่วงของลายเซ็นหลักของโปรแกรม C ที่ถูกต้องนั้นยิ่งใหญ่กว่ามาก

ประสิทธิภาพไม่ใช่ปัญหาของmainฟังก์ชั่น สามารถเข้าและออกได้เพียงครั้งเดียว (ทำเครื่องหมายการเริ่มต้นและการสิ้นสุดของโปรแกรม) ตามมาตรฐาน C ++ สำหรับ C main()อนุญาตให้ป้อนซ้ำได้ แต่ควรหลีกเลี่ยง


69
สามารถเข้า / ออก main ได้หลายครั้ง แต่โปรแกรมนั้นอาจจะไม่ได้รับรางวัลการออกแบบใด ๆ )
korona

13
C99 ยังมีคุณสมบัติ C + + mis- ผิดที่ถึงจุดสิ้นสุดของ main () ฟังก์ชั่นเทียบเท่ากับกลับ 0 - ถ้า main () ถูกกำหนดไว้เพื่อกลับประเภทที่เข้ากันได้กับ int (ส่วน 5.1.2.2.3)
Jonathan Leffler

62
การป้อนหลักใหม่ไม่ถูกต้อง C ++ อย่างชัดเจนในมาตรฐาน 3.6.1.3 'รัฐหลักจะไม่ถูกนำมาใช้ภายในโปรแกรม'
workmad3

117
stdlib.h มอบ EXIT_SUCCESS และ EXIT_FAILURE เพื่อจุดประสงค์นี้
Clay

20
0 และไม่ใช่ศูนย์นั้นถูกต้อง แต่ไม่มีความหมายเลยสำหรับคนที่อ่านรหัสของคุณ คำถามนี้เป็นข้อพิสูจน์ว่าผู้คนไม่รู้รหัสที่ถูกต้อง / ไม่ถูกต้อง EXIT_SUCCESS / EXIT_FAILURE ชัดเจนยิ่งขึ้น
JaredPar

169

คำตอบที่ยอมรับนั้นดูเหมือนจะถูกกำหนดเป้าหมายสำหรับ C ++ ดังนั้นฉันคิดว่าฉันจะเพิ่มคำตอบที่เกี่ยวข้องกับ C และสิ่งนี้แตกต่างกันในสองสามวิธี

ISO / IEC 9899: 1989 (C90):

main() ควรประกาศเป็น:

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

หรือเทียบเท่า. ตัวอย่างเช่นint main(int argc, char *argv[])เทียบเท่ากับที่สอง นอกจากนี้intประเภทการส่งคืนสามารถละเว้นได้เนื่องจากเป็นค่าเริ่มต้น

หากการติดตั้งใช้งานนั้นmain()สามารถประกาศได้ด้วยวิธีอื่น แต่สิ่งนี้ทำให้การใช้งานโปรแกรมถูกกำหนดไว้และไม่ได้ปฏิบัติตามอย่างเคร่งครัดอีกต่อไป

มาตรฐานกำหนด 3 ค่าสำหรับการส่งคืนที่สอดคล้องอย่างเคร่งครัด (นั่นคือไม่ได้ขึ้นอยู่กับพฤติกรรมการใช้งานที่กำหนดไว้): 0และEXIT_SUCCESSสำหรับการยกเลิกที่ประสบความสำเร็จและEXIT_FAILUREสำหรับการยกเลิกที่ไม่สำเร็จ ค่าอื่น ๆ ที่ไม่ได้มาตรฐานและการใช้งานที่กำหนดไว้ main()ต้องมีreturnคำชี้แจงที่ชัดเจนในตอนท้ายเพื่อหลีกเลี่ยงพฤติกรรมที่ไม่ได้กำหนด

ในที่สุดก็ไม่มีอะไรผิดปกติจากมุมมองมาตรฐานกับการโทรmain()จากโปรแกรม

ISO / IEC 9899: 1999 (C99):

สำหรับ C99 ทุกอย่างเหมือนกับข้างบนยกเว้น:

  • intประเภทผลตอบแทนอาจจะไม่ถูกมองข้าม
  • main()คุณอาจหลงลืมคำสั่งกลับจาก หากคุณทำและเสร็จมีนัยmain()return 0

1
@Lundin ฉันไม่คิดว่าคุณต้องการใบเสนอราคาเพื่อบอกว่ามีคนที่ได้รับอนุญาตให้คอมไพเลอร์ที่ยอมรับโปรแกรมที่ไม่ได้มาตรฐานหรือมีคอมไพเลอร์ที่ไม่เป็นมาตรฐาน นั่นเป็นความรู้ทั่วไปและสามัญสำนึก
KABoissonneault

4
@KABoissonneault พฤติกรรมที่กำหนดใช้งานเป็นคำจากมาตรฐานซึ่งตรงข้ามกับพฤติกรรมที่ไม่มีเอกสารอย่างสมบูรณ์ หากคุณใช้บางสิ่งที่ระบุว่าเป็นพฤติกรรมที่กำหนดโดยการนำไปใช้คุณยังคงปฏิบัติตามมาตรฐาน ในกรณีนี้ C89 ซึ่งอ้างถึงไม่มีรายการพฤติกรรมที่กำหนดไว้ในการใช้งานดังกล่าวดังนั้นจึงจำเป็นต้องมีการอ้างเพื่อพิสูจน์ว่าเขาไม่ได้ทำสิ่งต่าง ๆ ขึ้นมาจากสีน้ำเงิน
Lundin

1
@Lundin คุณเห็นวิธีนี้ผิด สิ่งที่เรากำลังพูดถึงไม่ใช่พฤติกรรมที่กำหนดไว้ในการนำไปใช้เรากำลังพูดถึงการนำไปปฏิบัติที่เบี่ยงเบนไปจากมาตรฐานหากพวกเขาเลือก มันเหมือนเด็กที่ไม่เชื่อฟังพ่อแม่ของพวกเขา: คุณไม่จำเป็นต้องมีใบเสนอราคาจากผู้ปกครองเพื่อบอกคุณว่าเด็ก ๆ สามารถต่อต้านสิ่งที่พ่อแม่พูดได้ คุณเพิ่งรู้ว่าช่วงเวลาที่เด็กเลือกที่จะทำเช่นนั้นพวกเขาไม่ได้ปฏิบัติตามกิลเดลีนของพ่อแม่อีกต่อไป
KABoissonneault

2
@KABoissonneault ที่ผมยกมาในส่วนความคิดเห็นของฉันแน่นอนเกี่ยวกับพฤติกรรมการใช้งานที่กำหนดไว้ (เมื่อเทียบกับส่วนขยายของคอมไพเลอร์ที่ไม่ได้มาตรฐาน .) ดังนั้นฉันพูดคุยเกี่ยวกับพฤติกรรมการใช้งานที่กำหนดไว้ หากคุณกำลังพูดคนเดียวเกี่ยวกับเรื่องอื่นขอให้โชคดีกับเรื่องนี้
Lundin

1
@Lundin ผมคิดว่าถ้อยคำในใบเสนอราคาที่มีการทำให้เกิดความสับสน (ส่วนหนึ่งที่พวกเขากล่าวว่า "แต่นี้จะทำให้การใช้งานโปรแกรมที่กำหนดไว้") แต่ผมค่อนข้างมั่นใจว่าคนที่ได้พูดคุยเกี่ยวกับพฤติกรรมที่ไม่ได้มาตรฐาน (ตามที่กล่าวใน "หากมีการดำเนินการอนุญาตให้ "และ" และไม่ปฏิบัติตาม [มาตรฐาน] ") อย่างเคร่งครัดเมื่อเทียบกับพฤติกรรมที่กำหนดไว้ในการใช้งานจริง บุคคลนั้นควรพูดคำตอบของพวกเขาอย่างแน่นอน แต่ฉันก็ยังไม่คิดว่าจำเป็นต้องมีการอ้างอิงจากมาตรฐาน
KABoissonneault

117

มาตรฐาน C - สภาพแวดล้อมที่โฮสต์

สำหรับสภาพแวดล้อมที่โฮสต์ (เป็นเรื่องปกติ) มาตรฐาน C11 (ISO / IEC 9899: 2011) กล่าวว่า:

5.1.2.2.1 การเริ่มต้นโปรแกรม

mainฟังก์ชั่นที่เรียกว่าเมื่อเริ่มต้นโปรแกรมการตั้งชื่อ การใช้งานไม่ประกาศต้นแบบสำหรับฟังก์ชั่นนี้ มันจะถูกกำหนดด้วยประเภทผลตอบแทนintและไม่มีพารามิเตอร์:

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

หรือมีพารามิเตอร์สองตัว (เรียกที่นี่ว่าargcและargvแม้ว่าอาจใช้ชื่อใดก็ได้เนื่องจากเป็นชื่อท้องถิ่นสำหรับฟังก์ชันที่มีการประกาศไว้):

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

หรือเทียบเท่า; 10)หรือในลักษณะอื่น ๆ ที่กำหนดโดยการนำไปปฏิบัติ

หากมีการประกาศพารามิเตอร์ของฟังก์ชั่นหลักจะต้องปฏิบัติตามข้อ จำกัด ดังต่อไปนี้:

  • ค่าของargcจะไม่เป็นค่าลบ
  • argv[argc] จะต้องเป็นตัวชี้โมฆะ
  • หากค่าargcมากกว่าศูนย์สมาชิกอาเรย์argv[0]ผ่านการ argv[argc-1]รวมจะต้องมีพอยน์เตอร์ไปยังสตริงซึ่งจะได้รับค่าที่กำหนดโดยการนำไปปฏิบัติโดยสภาพแวดล้อมของโฮสต์ก่อนที่จะเริ่มโปรแกรม จุดประสงค์คือเพื่อให้ข้อมูลโปรแกรมที่กำหนดก่อนการเริ่มต้นโปรแกรมจากที่อื่นในสภาพแวดล้อมที่โฮสต์ หากสภาพแวดล้อมโฮสต์ไม่สามารถจัดหาสตริงด้วยตัวอักษรในทั้งตัวพิมพ์ใหญ่และตัวพิมพ์เล็กการใช้งานต้องทำให้แน่ใจว่าได้รับสตริงเป็นตัวพิมพ์เล็ก
  • หากค่าargcมากกว่าศูนย์สตริงที่ชี้ไปโดยจะargv[0] แทนชื่อโปรแกรม argv[0][0]จะต้องเป็นอักขระ null หากชื่อโปรแกรมไม่พร้อมใช้งานจากสภาพแวดล้อมโฮสต์ ถ้าค่าargcมากกว่าหนึ่งสตริงที่ชี้ไปยังargv[1]ผ่านจะargv[argc-1] แทนพารามิเตอร์โปรแกรม
  • พารามิเตอร์argcและargvสายอักขระที่ชี้ไปยังargvอาร์เรย์จะสามารถแก้ไขได้โดยโปรแกรมและรักษาค่าที่เก็บไว้ล่าสุดระหว่างการเริ่มต้นโปรแกรมและการยกเลิกโปรแกรม

10)ดังนั้นintสามารถถูกแทนที่ด้วยชื่อ typedef ที่กำหนดเป็นintหรือประเภทของargvสามารถเขียนเป็น char **argvและอื่น ๆ

การยุติโปรแกรมใน C99 หรือ C11

ค่าที่ส่งคืนจากmain()จะถูกส่งไปยัง 'สภาพแวดล้อม' ในวิธีที่กำหนดไว้ในการนำไปใช้

5.1.2.2.3 การยุติโปรแกรม

1 หากประเภทส่งคืนของmainฟังก์ชั่นเป็นประเภทที่เข้ากันได้กับintการกลับมาจากการเรียกครั้งแรกไปยังmainฟังก์ชั่นเทียบเท่ากับการเรียกexitฟังก์ชั่นที่มีค่าส่งกลับโดยmainฟังก์ชั่นเป็นอาร์กิวเมนต์ 11) การเข้าถึงฟังก์ชัน}ที่ยกเลิก mainฟังก์ชันส่งคืนค่า 0 หากชนิดส่งคืนไม่สามารถทำงานร่วมกันได้intสถานะการยกเลิกที่ส่งคืนไปยังสภาพแวดล้อมโฮสต์จะไม่ได้รับการระบุ

11)ตาม 6.2.4 อายุการใช้งานของวัตถุที่มีระยะเวลาการจัดเก็บอัตโนมัติที่ประกาศไว้main จะสิ้นสุดลงในกรณีก่อนหน้าแม้ว่าจะไม่ได้อยู่ในที่หลัง

โปรดทราบว่า0ได้รับคำสั่งเป็น 'สำเร็จ' คุณสามารถใช้EXIT_FAILUREและEXIT_SUCCESSจาก<stdlib.h>หากคุณต้องการ แต่มีการจัดตั้งเป็นอย่างดีและ 0 คือ 1 ดูรหัสทางออกที่มากกว่า 255 - เป็นไปได้หรือไม่ .

ใน C89 (และด้วยเหตุนี้ใน Microsoft C) ไม่มีคำสั่งเกี่ยวกับสิ่งที่เกิดขึ้นหากmain()ฟังก์ชันส่งคืน แต่ไม่ได้ระบุค่าส่งคืน มันจึงนำไปสู่พฤติกรรมที่ไม่ได้กำหนด

7.22.4.4 exitฟังก์ชั่น

¶5ในที่สุดการควบคุมจะกลับสู่สภาพแวดล้อมของโฮสต์ หากค่าstatusเป็นศูนย์หรือEXIT_SUCCESSมีการส่งคืนฟอร์มที่กำหนดโดยการนำไปปฏิบัติของสถานะการยกเลิกที่สำเร็จ หากค่าของstatusคือจะส่งคืนEXIT_FAILUREแบบฟอร์มที่กำหนดโดยการนำไปปฏิบัติของสถานะการเลิกจ้างที่ไม่สำเร็จ มิฉะนั้นสถานะที่ส่งคืนจะถูกกำหนดโดยการนำไปปฏิบัติ

มาตรฐาน C ++ - สภาพแวดล้อมที่โฮสต์

มาตรฐาน C ++ 11 (ISO / IEC 14882: 2011) พูดว่า:

3.6.1 ฟังก์ชั่นหลัก [basic.start.main]

¶1โปรแกรมจะมีฟังก์ชั่นระดับโลกที่เรียกว่า main ซึ่งเป็นจุดเริ่มต้นที่กำหนดของโปรแกรม [ ... ]

¶2การดำเนินการจะต้องไม่กำหนดฟังก์ชันหลักไว้ล่วงหน้า ฟังก์ชั่นนี้จะต้องไม่โอเวอร์โหลด มันจะต้องมีชนิดผลตอบแทนประเภท int แต่มิฉะนั้นประเภทของมันคือการใช้งานที่กำหนดไว้ การใช้งานทั้งหมดจะต้องอนุญาตทั้งคำจำกัดความหลักดังต่อไปนี้:

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

และ

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

ในรูปแบบหลังargcจะเป็นจำนวนข้อโต้แย้งที่ส่งผ่านไปยังโปรแกรมจากสภาพแวดล้อมที่โปรแกรมจะทำงาน ถ้าargcไม่ใช่ศูนย์อาร์กิวเมนต์เหล่านี้จะถูกส่งargv[0] ผ่านargv[argc-1]เป็นพอยน์เตอร์สำหรับอักขระเริ่มต้นของสตริงหลายไบต์ที่สิ้นสุดด้วยค่า null (NTMBSs) (17.5.2.1.4.2) และargv[0]จะเป็นตัวชี้ไปยังอักขระเริ่มต้นของ NTMBS ที่แสดงถึงชื่อที่ใช้ ""เรียกใช้โปรแกรมหรือ ค่าของargcจะไม่เป็นลบ ค่าของargv[argc] จะเป็น 0 [หมายเหตุ: ขอแนะนำให้เพิ่มพารามิเตอร์เพิ่มเติม (ทางเลือก) ใด ๆ หลังจากargvนั้น - บันทึกย่อ]

¶3 mainไม่สามารถใช้ฟังก์ชั่นภายในโปรแกรม การเชื่อมโยง (3.5) ของmainเป็นการนำไปปฏิบัติ [ ... ]

¶5คำสั่ง return ใน main มีผลต่อการออกจากฟังก์ชั่นหลัก (ทำลายวัตถุใด ๆ ที่มีระยะเวลาการเก็บข้อมูลอัตโนมัติ) และการเรียกstd::exitด้วยค่าตอบแทนเป็นอาร์กิวเมนต์ หากการควบคุมมาถึงจุดสิ้นสุดของ main โดยไม่พบคำสั่ง return ผลลัพธ์ที่ได้คือการเรียกใช้งาน

return 0;

มาตรฐาน C ++ บอกอย่างชัดเจนว่า "มัน [ฟังก์ชั่นหลัก] จะมีประเภทผลตอบแทนintแต่มิฉะนั้นประเภทของมันคือการใช้งานที่กำหนดไว้" และต้องมีสองลายเซ็นเดียวกันกับมาตรฐาน C ที่จะได้รับการสนับสนุนเป็นตัวเลือก ดังนั้น 'void main ()' จึงไม่ได้รับอนุญาตโดยตรงจากมาตรฐาน C ++ แม้ว่าจะไม่มีสิ่งใดที่จะทำเพื่อหยุดการใช้งานที่ไม่ได้มาตรฐานเพื่อให้มีทางเลือกอื่น โปรดทราบว่า C ++ ห้ามผู้ใช้จากการโทรmain(แต่มาตรฐาน C ไม่ได้)

มีย่อหน้าของ§18.5เป็นเริ่มต้นและการสิ้นสุดใน C ++ 11 มาตรฐานที่เป็นเหมือนวรรคจาก§7.22.4.4 ฟังก์ชั่นในมาตรฐาน C11 (ยกมาข้างต้น) นอกเหนือจากเชิงอรรถ (ซึ่งเอกสารเพียงว่าและจะมีการกำหนด ใน)exitEXIT_SUCCESSEXIT_FAILURE<cstdlib>

มาตรฐาน C - ส่วนขยายทั่วไป

คลาสสิกระบบ Unix รองรับตัวแปรที่สาม:

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

อาร์กิวเมนต์ที่สามคือรายการพอยน์เตอร์ที่สิ้นสุดด้วย null ซึ่งแต่ละตัวเป็นตัวแปรสภาพแวดล้อมที่มีชื่อเครื่องหมายเท่ากับและค่า (อาจว่างเปล่า) หากคุณไม่ได้ใช้สิ่งนี้คุณยังสามารถเข้าถึงสภาพแวดล้อมผ่าน ' extern char **environ;' ตัวแปรโกลบอลนี้เป็นค่าเฉพาะใน POSIX ซึ่งไม่มีส่วนหัวที่ประกาศ

สิ่งนี้ได้รับการยอมรับจากมาตรฐาน C ว่าเป็นส่วนขยายทั่วไปที่บันทึกไว้ในภาคผนวก J:

J.5.1 ข้อโต้แย้งด้านสิ่งแวดล้อม

¶1ในสภาพแวดล้อมที่โฮสต์ฟังก์ชั่นหลักจะได้รับอาร์กิวเมนต์ที่สามchar *envp[]ซึ่งชี้ไปยังอาเรย์ปลายพอยน์เตอร์ที่สิ้นสุดด้วยค่าcharแต่ละค่าซึ่งชี้ไปยังสตริงที่ให้ข้อมูลเกี่ยวกับสภาพแวดล้อมสำหรับการดำเนินการของโปรแกรมนี้ (5.1 2.2.1)

Microsoft C

Microsoft VS 2010คอมไพเลอร์เป็นที่น่าสนใจ เว็บไซต์บอกว่า:

ไวยากรณ์การประกาศสำหรับ main คือ

 int main();

หรืออาจเลือก

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

อีกทางเลือกหนึ่งฟังก์ชั่นmainและwmainสามารถประกาศเป็นคืนvoid(ไม่มีค่าตอบแทน) หากคุณประกาศmainหรือwmainคืนค่าเป็นโมฆะคุณจะไม่สามารถส่งคืนรหัสทางออกให้กับกระบวนการหลักหรือระบบปฏิบัติการโดยใช้คำสั่ง return ในการส่งคืนรหัสออกเมื่อmainหรือwmainประกาศว่าvoidคุณต้องใช้exitฟังก์ชัน

มันไม่ชัดเจนสำหรับฉันว่าเกิดอะไรขึ้น (รหัสทางออกใดที่ส่งคืนไปยังพาเรนต์หรือระบบปฏิบัติการ) เมื่อโปรแกรมที่void main()ออกไม่ทำงานและเว็บไซต์ MS ก็เงียบเช่นกัน

ที่น่าสนใจคือ MS ไม่ได้กำหนดเวอร์ชันสองข้อโต้แย้งของmain()มาตรฐาน C และ C ++ ที่ต้องการ เพียงกำหนดรูปแบบอาร์กิวเมนต์สามแบบโดยที่อาร์กิวเมนต์ที่สามคือchar **envpตัวชี้ไปยังรายการของตัวแปรสภาพแวดล้อม

หน้า Microsoft ยังแสดงรายการทางเลือกอื่น ๆwmain()ซึ่งใช้สายอักขระกว้างและอื่น ๆ

หน้า Microsoft Visual Studio 2005รุ่นนี้ไม่มีรายชื่อvoid main()เป็นทางเลือก รุ่นจาก Microsoft Visual Studio 2008เป็นต้นไปทำ

มาตรฐาน C - สภาพแวดล้อมอิสระ

ตามที่ระบุไว้ก่อนหน้าข้อกำหนดด้านบนมีผลกับสภาพแวดล้อมที่โฮสต์ หากคุณกำลังทำงานกับสภาพแวดล้อมอิสระ (ซึ่งเป็นทางเลือกให้กับสภาพแวดล้อมที่โฮสต์) มาตรฐานนั้นมีน้อยกว่าที่จะพูด สำหรับสภาพแวดล้อมที่เป็นอิสระฟังก์ชันที่เรียกใช้เมื่อเริ่มต้นโปรแกรมไม่จำเป็นต้องถูกเรียกใช้mainและไม่มีข้อ จำกัด สำหรับชนิดส่งคืน มาตรฐานบอกว่า:

5.1.2 สภาพแวดล้อมในการดำเนินการ

มีการกำหนดสองสภาวะแวดล้อมการทำงาน: อิสระและโฮสต์ ในทั้งสองกรณีการเริ่มต้นโปรแกรมเกิดขึ้นเมื่อมีการเรียกใช้ฟังก์ชัน C ที่กำหนดโดยสภาพแวดล้อมการดำเนินการ วัตถุทั้งหมดที่มีระยะเวลาการจัดเก็บแบบคงที่จะต้องเริ่มต้น (ตั้งค่าเป็นค่าเริ่มต้น) ก่อนที่จะเริ่มโปรแกรม ลักษณะและระยะเวลาของการเริ่มต้นดังกล่าวไม่ได้ระบุไว้เป็นอย่างอื่น การยุติโปรแกรมส่งคืนการควบคุมสภาพแวดล้อมการดำเนินการ

5.1.2.1 สภาพแวดล้อมอิสระ

ในสภาพแวดล้อมที่เป็นอิสระ (ซึ่งการดำเนินการของโปรแกรม C อาจเกิดขึ้นโดยไม่ได้รับประโยชน์จากระบบปฏิบัติการ) ชื่อและประเภทของฟังก์ชั่นที่เรียกเมื่อเริ่มต้นโปรแกรมนั้นจะถูกกำหนดตามการนำไปใช้ สิ่งอำนวยความสะดวกของไลบรารีใด ๆ ที่พร้อมใช้งานสำหรับโปรแกรมอิสระนอกเหนือจากชุดขั้นต่ำที่กำหนดไว้ในข้อ 4 จะถูกกำหนดตามการนำไปใช้

ผลกระทบของการยกเลิกโปรแกรมในสภาพแวดล้อมอิสระนั้นกำหนดโดยการนำไปปฏิบัติ

การอ้างอิงโยงไปยังข้อ 4 ความสอดคล้องหมายถึงสิ่งนี้:

¶5 โปรแกรมที่สอดคล้องอย่างเคร่งครัดจะใช้เฉพาะคุณสมบัติเหล่านั้นของภาษาและห้องสมุดที่ระบุในมาตรฐานสากลนี้ 3)มันจะไม่ผลิตผลลัพธ์ขึ้นอยู่กับพฤติกรรมที่ไม่ได้กำหนดไม่ได้กำหนดหรือไม่ได้กำหนดไว้และจะต้องไม่เกินขีด จำกัด การปฏิบัติขั้นต่ำ

¶6ทั้งสองรูปแบบของการดำเนินงานตามนโยบายจะเป็นเจ้าภาพและอิสระ การใช้งานโฮสต์ที่สอดคล้องจะต้องยอมรับโปรแกรมใด ๆ ที่สอดคล้องกันอย่างเคร่งครัด การดำเนินงานตามนโยบายอิสระจะยอมรับโปรแกรมใด ๆ ตามนโยบายอย่างเคร่งครัดซึ่งในการใช้งานของคุณสมบัติที่ระบุไว้ในข้อห้องสมุด (ข้อ 7) ถูกกักขังอยู่ในเนื้อหาของส่วนหัวมาตรฐาน<float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, และ<stdint.h> <stdnoreturn.h>การใช้งานที่สอดคล้องกันอาจมีส่วนขยาย (รวมถึงฟังก์ชั่นห้องสมุดเพิ่มเติม) หากไม่ได้ปรับเปลี่ยนพฤติกรรมของโปรแกรมที่เข้ากันได้อย่างเคร่งครัด 4)

¶7 โปรแกรมที่สอดคล้องกันนั้นเป็นโปรแกรมที่เป็นที่ยอมรับในการใช้งานที่สอดคล้อง 5)

3)โปรแกรมที่สอดคล้องอย่างเคร่งครัดสามารถใช้คุณสมบัติตามเงื่อนไข (ดู 6.10.8.3) หากการใช้งานได้รับการปกป้องโดยคำสั่ง preprocessing การรวมตามเงื่อนไขที่เหมาะสมโดยใช้แมโครที่เกี่ยวข้อง ตัวอย่างเช่น:

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

4)นี่ก็หมายความว่าการดำเนินการที่สอดคล้องกันขอสงวนไม่มีตัวระบุอื่นนอกเหนือจากที่สงวนไว้อย่างชัดเจนในมาตรฐานสากลนี้

5)โปรแกรมที่สอดคล้องอย่างเคร่งครัดมีวัตถุประสงค์เพื่อให้สามารถพกพาได้มากที่สุดระหว่างการใช้งานที่สอดคล้องกัน โปรแกรมการปรับให้สอดคล้องอาจขึ้นอยู่กับคุณสมบัติที่ไม่สามารถพกพาได้ของการใช้งานที่สอดคล้อง

เป็นที่สังเกตได้ว่าส่วนหัวเดียวเท่านั้นที่ต้องการสภาพแวดล้อมอิสระที่กำหนดฟังก์ชั่นใด ๆ ที่เป็นจริง<stdarg.h>(และแม้กระทั่งที่อาจเป็น - และมักจะ - แมโครเพียง)

มาตรฐาน C ++ - สภาพแวดล้อมอิสระ

เช่นเดียวกับที่มาตรฐาน C รู้จักทั้งสภาพแวดล้อมที่โฮสต์และอิสระดังนั้นมาตรฐาน C ++ ก็เช่นกัน (ราคาจาก ISO / IEC 14882: 2011)

1.4 การปฏิบัติตามการนำไปปฏิบัติ [intro.compliance]

¶7สองชนิดของการใช้งานจะมีการกำหนดที่: เจ้าภาพการดำเนินงานและการดำเนินงานอิสระ สำหรับการนำไปปฏิบัติที่โฮสต์มาตรฐานสากลนี้จะกำหนดชุดของห้องสมุดที่มีอยู่ การใช้งานอิสระเป็นสิ่งที่การดำเนินการอาจเกิดขึ้นโดยไม่ได้รับประโยชน์จากระบบปฏิบัติการและมีชุดของไลบรารีที่ใช้งานที่กำหนดไว้ซึ่งรวมถึงไลบรารีสนับสนุนภาษาบางอย่าง (17.6.1.3)

implementation8 การนำไปปฏิบัติที่สอดคล้องกันอาจมีส่วนขยาย (รวมถึงฟังก์ชั่นห้องสมุดเพิ่มเติม) โดยที่พวกเขาจะไม่เปลี่ยนแปลงพฤติกรรมของโปรแกรมที่มีรูปแบบที่เหมาะสม การใช้งานจำเป็นต้องมีการวินิจฉัยโปรแกรมที่ใช้ส่วนขยายที่ไม่ได้มาตรฐานตามมาตรฐานสากลนี้ อย่างไรก็ตามเมื่อเสร็จสิ้นแล้วพวกเขาสามารถรวบรวมและดำเนินการโปรแกรมดังกล่าวได้

implementation9 การนำไปปฏิบัติแต่ละครั้งจะต้องมีเอกสารประกอบที่ระบุโครงสร้างที่ได้รับการสนับสนุนตามเงื่อนไขทั้งหมดซึ่งไม่สนับสนุนและกำหนดลักษณะเฉพาะของสถานที่ทั้งหมด 3

3)เอกสารนี้ยังกำหนดพฤติกรรมการใช้งานที่กำหนดไว้; ดู 1.9

17.6.1.3 การติดตั้งอิสระ [การปฏิบัติตาม]

มีการกำหนดการใช้งานสองประเภท: โฮสต์และอิสระ (1.4) สำหรับการนำไปปฏิบัติที่โฮสต์มาตรฐานสากลนี้จะอธิบายชุดของส่วนหัวที่มีอยู่

การใช้งานอิสระมีชุดของส่วนหัวที่กำหนดไว้ ชุดนี้จะต้องมีอย่างน้อยส่วนหัวที่แสดงในตารางที่ 16

รุ่นที่จัดของส่วนหัว<cstdlib>จะประกาศอย่างน้อยฟังก์ชั่นabort, atexit, at_quick_exit, exitและquick_exit(18.5) ส่วนหัวอื่น ๆ ที่ระบุไว้ในตารางนี้จะต้องเป็นไปตามข้อกำหนดเช่นเดียวกับการใช้งานโฮสต์

ตารางที่ 16 - ส่วนหัว C ++ สำหรับการปรับใช้อิสระ

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?

§5.1.2.2.1มาตรฐานของ C11 แสดงให้เห็นมาตรฐานสัญกรณ์ที่ต้องการ -  int main(void)- แต่ก็ยังมีสองตัวอย่างในมาตรฐานที่แสดงint main(): §6.5.3.4¶8และ§6.7.6.3¶20 ตอนนี้เป็นสิ่งสำคัญที่จะต้องทราบว่าตัวอย่างไม่ใช่ 'เชิงบรรทัดฐาน'; มันเป็นเพียงตัวอย่างเท่านั้น หากมีข้อบกพร่องในตัวอย่างพวกเขาจะไม่ส่งผลกระทบโดยตรงต่อข้อความหลักของมาตรฐาน ที่กล่าวว่าพวกเขาบ่งบอกอย่างมากถึงพฤติกรรมที่คาดหวังดังนั้นหากมาตรฐานรวมint main()อยู่ในตัวอย่างมันแสดงให้เห็นint main()ว่าไม่ได้รับอนุญาตแม้ว่ามันจะไม่ได้เป็นสัญลักษณ์ที่ต้องการ

6.5.3.4 sizeofและ_Alignofตัวดำเนินการ

...

¶8ตัวอย่าง 3 ในตัวอย่างนี้ขนาดของอาร์เรย์ความยาวแปรผันถูกคำนวณและส่งคืนจากฟังก์ชัน:

#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: นิยามฟังก์ชั่นเหมือนint main(){ … }ไม่ระบุว่าฟังก์ชั่นจะไม่มีข้อโต้แย้ง แต่ไม่ได้ให้ต้นแบบฟังก์ชั่น AFAICT สำหรับmain()ปัญหานั้นไม่ค่อยมีอยู่ หมายความว่าหากคุณมีการโทรซ้ำไปmain()ยังอาร์กิวเมนต์นั้นจะไม่ถูกตรวจสอบ สำหรับฟังก์ชั่นอื่น ๆ มันเป็นปัญหามากกว่า - คุณต้องการต้นแบบในขอบเขตจริง ๆ เมื่อมีการเรียกใช้ฟังก์ชันเพื่อให้แน่ใจว่าอาร์กิวเมนต์นั้นถูกต้อง
Jonathan Leffler

1
@DavidBowling: ปกติแล้วคุณจะไม่โทรmain()ซ้ำแบบนอกสถานที่อย่าง IOCCC ฉันมีโปรแกรมทดสอบที่ทำ - ส่วนใหญ่เป็นของแปลกใหม่ หากคุณมีint i = 0; int main() { if (i++ < 10) main(i, i * i); return 0; }และคอมไพล์ด้วย GCC และไม่รวม-Wstrict-prototypesมันจะรวบรวมอย่างสมบูรณ์ภายใต้คำเตือนที่เข้มงวด หากเป็นmain(void)เช่นนั้นจะไม่สามารถรวบรวมได้
Jonathan Leffler

61

ผมเชื่อว่าmain()ควรจะกลับอย่างใดอย่างหนึ่งหรือEXIT_SUCCESS EXIT_FAILUREพวกเขาถูกกำหนดไว้ในstdlib.h


20
0 ยังเป็นมาตรฐาน
Chris Young

2
@ChrisYoung มีEXIT_SUCCESSและEXIT_FAILUREเพราะบางระบบปฏิบัติการประวัติศาสตร์ (VMS?) ใช้หมายเลขที่แตกต่างจาก 0 เพื่อแสดงถึงความสำเร็จ มันเป็น 0 ทุกวันนี้
fuz

5
@FZZxxl คุณถูกต้อง แต่นั่นไม่ได้ขัดแย้งกับความคิดเห็นของฉัน EXIT_SUCCESS สามารถไม่ใช่ศูนย์ แต่มาตรฐาน (C89, C99, C11) ทั้งหมดกำหนด 0 (เช่นเดียวกับ EXIT_SUCCESS) ให้เป็นรูปแบบที่กำหนดโดยการนำไปปฏิบัติของสถานะการยกเลิกสำเร็จ
Chris Young

2
@FUZxxl: เป็นเรื่องจริงที่ VMS ใช้ค่าคี่ (เช่น 1) เพื่อระบุความสำเร็จและแม้กระทั่งค่า (เช่น 0) เพื่อระบุความล้มเหลว น่าเสียดายที่มาตรฐาน ANSI C ดั้งเดิมตีความว่าหมายความว่า EXIT_SUCCESS ต้องเป็น 0 ดังนั้นการส่งคืน EXIT_SUCCESS จากหลักจะมีพฤติกรรมที่ไม่ถูกต้องใน VMS สิ่งที่พกพาได้สำหรับ VMS คือการใช้exit(EXIT_SUCCESS)ซึ่งทำสิ่งที่ถูกต้องเสมอ
Adrian McCarthy

1
5.1.2.2.3 "ถ้าประเภทส่งคืนของฟังก์ชั่นหลักเป็นชนิดที่เข้ากันได้กับ int การส่งคืนจากการเรียกครั้งแรกไปยังฟังก์ชั่นหลักเทียบเท่ากับการเรียกฟังก์ชั่นทางออกด้วยค่าที่ส่งกลับโดยฟังก์ชั่นหลักเป็นอาร์กิวเมนต์ 11) ถึง} ที่ยุติฟังก์ชั่นหลักส่งกลับค่า 0 "
Lundin

38

โปรดทราบว่ามาตรฐาน C และ C ++ กำหนดการใช้งานสองประเภท: อิสระและโฮสต์

  • สภาพแวดล้อมที่โฮสต์ C90

    แบบฟอร์มที่อนุญาต1 :

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

    ความคิดเห็นที่:

    อดีตทั้งสองมีการระบุไว้อย่างชัดเจนว่าเป็นรูปแบบที่ได้รับอนุญาตอื่น ๆ ที่ได้รับอนุญาตโดยปริยายเพราะ C90 อนุญาตให้ "implicit int" สำหรับประเภทผลตอบแทนและฟังก์ชั่นพารามิเตอร์ ไม่อนุญาตให้ใช้รูปแบบอื่น

  • C90 สภาพแวดล้อมอิสระ

    อนุญาตให้ใช้แบบฟอร์มหรือชื่อหลักใดก็ได้2 .

  • C99 โฮสต์สภาพแวดล้อม

    แบบฟอร์มที่อนุญาต3 :

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

    ความคิดเห็นที่:

    C99 ลบ "implicit int" ดังนั้นจึงmain()ไม่ถูกต้อง

    ประโยคแปลก ๆ ที่คลุมเครือ "หรือในลักษณะอื่น ๆ ที่กำหนดโดยการนำไปปฏิบัติ" ได้ถูกนำเสนอ สิ่งนี้สามารถตีความได้ว่า "พารามิเตอร์ที่int main()อาจแตกต่างกัน" หรือ "หลักสามารถมีรูปแบบที่กำหนดใช้งานใด ๆ "

    คอมไพเลอร์บางคนเลือกที่จะตีความมาตรฐานในวิธีหลัง เนื้อหาไม่สามารถระบุได้อย่างง่ายดายว่าพวกเขาไม่ได้ปฏิบัติตามอย่างเคร่งครัดโดยอ้างถึงมาตรฐานในตัวเองเพราะมันเป็นที่คลุมเครือ

    อย่างไรก็ตามเพื่อให้รูปแบบป่าที่สมบูรณ์main()อาจไม่ใช่ (?) ไม่ใช่ความตั้งใจของประโยคใหม่นี้ เหตุผล C99 (ไม่ใช่กฎเกณฑ์) หมายความว่าประโยคที่ว่าหมายถึงพารามิเตอร์เพิ่มเติมเพื่อ4int main

    แต่ส่วนสำหรับการยกเลิกโปรแกรมสภาพแวดล้อมที่เป็นเจ้าภาพไปแล้วการโต้เถียงเกี่ยวกับกรณีที่หลักไม่ได้กลับ int 5 แม้ว่าส่วนนั้นจะไม่เป็นบรรทัดฐานสำหรับวิธีการประกาศหลัก แต่ก็มีความหมายอย่างชัดเจนว่าอาจมีการประกาศหลักด้วยวิธีการที่กำหนดไว้อย่างสมบูรณ์แม้ในระบบโฮสต์

  • C99 สภาพแวดล้อมอิสระ

    อนุญาตให้ใช้แบบฟอร์มหรือชื่อหลักใดก็ได้6 .

  • สภาพแวดล้อมที่โฮสต์ C11

    แบบฟอร์มที่อนุญาต7 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
  • สภาพแวดล้อมอิสระ C11

    อนุญาตให้ใช้แบบฟอร์มหรือชื่อหลักใดก็ได้8 .


โปรดทราบว่าint main()ไม่เคยถูกระบุว่าเป็นรูปแบบที่ถูกต้องสำหรับการใช้งานโฮสต์ใด ๆ ของ C ในเวอร์ชันใด ๆ ข้างต้น ใน C ซึ่งแตกต่างจาก C ++ ()และ(void)มีความหมายต่างกัน อดีตคือคุณลักษณะที่ล้าสมัยซึ่งอาจถูกลบออกจากภาษา ดูทิศทางภาษาในอนาคต C11:

6.11.6 ผู้ประกาศฟังก์ชั่น

การใช้ฟังก์ชั่น declarators ที่มีวงเล็บว่างเปล่า (ไม่ใช่ตัวประกาศชนิดพารามิเตอร์รูปแบบต้นแบบ) เป็นคุณสมบัติที่ล้าสมัย


  • สภาพแวดล้อมที่โฮสต์ C ++ 03

    แบบฟอร์มที่อนุญาต9 :

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

    ความคิดเห็นที่:

    หมายเหตุวงเล็บว่างเปล่าในแบบฟอร์มแรก C ++ และ C แตกต่างกันในกรณีนี้เพราะใน C ++ หมายความว่าฟังก์ชันไม่ใช้พารามิเตอร์ แต่ใน C หมายถึงว่ามันอาจใช้พารามิเตอร์ใด ๆ

  • สภาพแวดล้อมอิสระ C ++ 03

    ชื่อของฟังก์ชั่นที่เรียกว่าเมื่อเริ่มต้นคือการใช้งานที่กำหนดไว้ ถ้าชื่อmain()นั้นจะต้องเป็นไปตามแบบฟอร์มที่ระบุ10 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
  • สภาพแวดล้อมที่โฮสต์ C ++ 11

    รูปแบบที่อนุญาต11 :

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

    ความคิดเห็นที่:

    ข้อความมาตรฐานเปลี่ยนไป แต่มีความหมายเหมือนกัน

  • สภาพแวดล้อมอิสระ C ++ 11

    ชื่อของฟังก์ชั่นที่เรียกว่าเมื่อเริ่มต้นคือการใช้งานที่กำหนดไว้ ถ้าชื่อmain()นั้นจะต้องเป็นไปตามแบบฟอร์มที่ระบุไว้12 :

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

อ้างอิง

  1. ANSI X3.159-1989 2.1.2.2 สภาพแวดล้อมที่โฮสต์ "การเริ่มต้นโปรแกรม"

    ฟังก์ชั่นที่เรียกว่าเมื่อเริ่มต้นโปรแกรมมีชื่อ main การใช้งานประกาศต้นแบบไม่สำหรับฟังก์ชั่นนี้ มันจะต้องถูกกำหนดด้วยชนิดส่งคืนของ int และไม่มีพารามิเตอร์:

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

    หรือด้วยสองพารามิเตอร์ (เรียกที่นี่ว่า argc และ argv แม้ว่าชื่อใด ๆ อาจถูกนำมาใช้เนื่องจากพวกเขาอยู่ในท้องถิ่นเพื่อฟังก์ชั่นที่พวกเขาจะประกาศ):

    int main(int argc, char *argv[]) { /* ... */ }
  2. ANSI X3.159-1989 2.1.2.1 สภาพแวดล้อมอิสระ:

    ในสภาพแวดล้อมที่เป็นอิสระ (ซึ่งการดำเนินการของโปรแกรม C อาจเกิดขึ้นโดยไม่ได้รับประโยชน์จากระบบปฏิบัติการ) ชื่อและประเภทของฟังก์ชั่นที่เรียกเมื่อเริ่มต้นโปรแกรมนั้นจะถูกกำหนดตามการนำไปใช้

  3. ISO 9899: 1999 5.1.2.2 สภาพแวดล้อมที่โฮสต์ -> 5.1.2.2.1 การเริ่มต้นโปรแกรม

    ฟังก์ชั่นที่เรียกว่าเมื่อเริ่มต้นโปรแกรมมีชื่อ main การใช้งานประกาศต้นแบบไม่สำหรับฟังก์ชั่นนี้ มันจะต้องถูกกำหนดด้วยชนิดส่งคืนของ int และไม่มีพารามิเตอร์:

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

    หรือด้วยสองพารามิเตอร์ (เรียกที่นี่ว่า argc และ argv แม้ว่าชื่อใด ๆ อาจถูกนำมาใช้เนื่องจากพวกเขาอยู่ในท้องถิ่นเพื่อฟังก์ชั่นที่พวกเขาจะประกาศ):

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

    หรือเทียบเท่า 9) หรือในลักษณะอื่น ๆ ที่กำหนดโดยการนำไปปฏิบัติ

  4. เหตุผลสำหรับมาตรฐานสากล - ภาษาโปรแกรม - C, รุ่น 5.10 5.1.2.2 สภาพแวดล้อมที่โฮสต์ -> 5.1.2.2.1 การเริ่มต้นโปรแกรม

    พฤติกรรมของการขัดแย้งกับหลักและการทำงานร่วมกันของทางออกหลักและ atexit (ดู .20 7.20.4.2) ได้รับการประมวลผลเพื่อควบคุมความหลากหลายที่ไม่พึงประสงค์ในการเป็นตัวแทนของสตริง argv และในความหมายของค่าที่ส่งคืนโดยหลัก

    สเปคของ argc และ argv เป็นข้อโต้แย้งหลักตระหนักถึงการปฏิบัติก่อนหน้าอย่างกว้างขวาง argv [argc] จะต้องเป็นตัวชี้โมฆะเพื่อให้การตรวจสอบซ้ำซ้อนในตอนท้ายของรายการรวมถึงบนพื้นฐานของการปฏิบัติทั่วไป

    main เป็นฟังก์ชั่นเดียวที่สามารถประกาศได้แบบพกพาโดยมีอาร์กิวเมนต์เป็นศูนย์หรือสองข้อ (จำนวนอาร์กิวเมนต์ของฟังก์ชั่นอื่น ๆ จะต้องตรงกันระหว่างการเรียกใช้และการกำหนด) กรณีพิเศษนี้จะจดจำการฝึกฝนอย่างกว้างขวางในการทิ้งอาร์กิวเมนต์ไปยัง main เมื่อโปรแกรมไม่สามารถเข้าถึงสตริงอาร์กิวเมนต์ของโปรแกรม ในขณะที่การนำไปใช้งานหลายอย่างสนับสนุนการโต้แย้งมากกว่าสองหลัก แต่การปฏิบัติเช่นนี้ไม่ได้รับพร โปรแกรมที่กำหนด main ด้วยสามอาร์กิวเมนต์ไม่สอดคล้องอย่างเคร่งครัด (ดู§ J.5.1.)

  5. ISO 9899: 1999 5.1.2.2 สภาพแวดล้อมที่โฮสต์ -> 5.1.2.2.3 การยุติโปรแกรม

    หากประเภทการกลับมาของฟังก์ชั่นหลักเป็นชนิดที่เข้ากันได้กับ int, ผลตอบแทนจากการโทรเริ่มต้นไปยังฟังก์ชั่นหลักคือเทียบเท่ากับการเรียกฟังก์ชั่นทางออกที่มีค่าส่งกลับโดยหน้าที่หลักเป็นอาร์กิวเมนต์ของตน 11) ถึง}ที่สิ้นสุด ฟังก์ชั่นหลักส่งคืนค่า 0 หากประเภทการคืนไม่เข้ากันกับ int สถานะการเลิกจ้างที่ส่งคืนไปยังสภาพแวดล้อมโฮสต์จะไม่ได้รับการระบุ

  6. ISO 9899: 1999 5.1.2.1 สภาพแวดล้อมอิสระ

    ในสภาพแวดล้อมที่เป็นอิสระ (ซึ่งการดำเนินการของโปรแกรม C อาจเกิดขึ้นโดยไม่ได้รับประโยชน์จากระบบปฏิบัติการ) ชื่อและประเภทของฟังก์ชั่นที่เรียกเมื่อเริ่มต้นโปรแกรมนั้นจะถูกกำหนดตามการนำไปใช้

  7. ISO 9899: 2011 5.1.2.2 สภาพแวดล้อมที่โฮสต์ -> 5.1.2.2.1 การเริ่มต้นโปรแกรม

    ส่วนนี้เหมือนกับ C99 ที่อ้างถึงข้างต้น

  8. ISO 9899: 1999 5.1.2.1 สภาพแวดล้อมอิสระ

    ส่วนนี้เหมือนกับ C99 ที่อ้างถึงข้างต้น

  9. ISO 14882: 2003 3.6.1 ฟังก์ชั่นหลัก

    การดำเนินการจะต้องไม่กำหนดฟังก์ชันหลักไว้ล่วงหน้า ฟังก์ชั่นนี้จะต้องไม่โอเวอร์โหลด มันจะต้องมีชนิดผลตอบแทนประเภท int แต่มิฉะนั้นประเภทของมันคือการดำเนินการที่กำหนดไว้ การใช้งานทั้งหมดจะต้องอนุญาตทั้งคำจำกัดความหลักดังต่อไปนี้:

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

    และ

    int main(int argc, char* argv[]) { /* ... */ }
  10. ISO 14882: 2003 3.6.1 ฟังก์ชั่นหลัก

    มันเป็นการใช้งานที่กำหนดว่าต้องมีโปรแกรมในสภาพแวดล้อมอิสระเพื่อกำหนดฟังก์ชั่นหลักหรือไม่

  11. ISO 14882: 2011 3.6.1 ฟังก์ชั่นหลัก

    การดำเนินการจะต้องไม่กำหนดฟังก์ชันหลักไว้ล่วงหน้า ฟังก์ชั่นนี้จะต้องไม่โอเวอร์โหลด มันจะต้องมีชนิดผลตอบแทนประเภท int แต่มิฉะนั้นประเภทของมันคือการดำเนินการที่กำหนดไว้ การใช้งานทั้งหมดจะอนุญาตให้ทั้งสอง

    - ฟังก์ชั่นของ () คืนค่า int และ

    - ฟังก์ชั่นของ (int, ตัวชี้ไปยังตัวชี้เพื่อถ่าน) กลับ int

    เป็นประเภทหลัก (8.3.5)

  12. ISO 14882: 2011 3.6.1 ฟังก์ชั่นหลัก

    ส่วนนี้เหมือนกับ C ++ 03 ที่อ้างถึงข้างต้น


คำถามหนึ่งข้อ: มาตรฐาน C ++ หมายความว่าลายเซ็นของฟังก์ชั่นเริ่มต้นในสภาพแวดล้อมอิสระนั้นถูกกำหนดตามการนำไปใช้หรือไม่? ตัวอย่างเช่นการใช้งานอาจกำหนดฟังก์ชั่นเริ่มต้นให้เป็น: int my_startup_function ()หรือint my_startup_function (int argc, char *argv[])แต่มันสามารถมีตัวอย่างเช่น: char my_startup_function (long argc, int *argv[])เป็นฟังก์ชั่นเริ่มต้นเช่นกัน? ฉันเดาไม่ถูก นอกจากนี้ยังไม่ชัดเจนเช่นกันหรือไม่
Utku

@Utku มันสามารถมีลายเซ็นได้ตราบใดที่มันไม่ได้ตั้งชื่อmain()เพราะมันจะต้องใช้ลายเซ็นที่ระบุไว้ ฉันนึกภาพที่พบบ่อยที่สุดอย่างท่วมท้นvoid my_startup_function ()เนื่องจากไม่มีเหตุผลที่จะกลับมาจากโปรแกรมบนระบบอิสระ
Lundin

1
ฉันเห็น. แต่ถ้าได้รับอนุญาตให้ใช้ชื่อและลายเซ็นใด ๆ สำหรับฟังก์ชั่นเริ่มต้นทำไมไม่อนุญาตให้ใช้ลายเซ็นอื่นด้วยmainเช่นกัน? ขออภัยถ้าไม่ใช่คำถามที่ฉลาด แต่ฉันไม่เข้าใจเหตุผลที่อยู่เบื้องหลัง
Utku

@Utku C และ C ++ ต่างกันตรงนั้น สำหรับสาเหตุที่ C ++ บังคับใช้สิ่งนี้ฉันไม่รู้เลยว่าไม่มีเหตุผล ฉันสงสัยว่าผู้กระทำผิดหลัก (ปุนตั้งใจ) คือStroustrupซึ่งก่อนหน้านี้ประกาศว่าหลักต้องกลับ int ระยะเวลา เพราะเมื่อเขาสร้าง C ++ เวอร์ชันแรกเขาจะถูกใช้เพื่อโฮสต์ระบบเท่านั้น ในโพสต์ที่เชื่อมโยง Stroustrup ยังคงหลงลืมเกี่ยวกับการมีอยู่ของการใช้งานอิสระ: ยกตัวอย่างเช่นเขาอ้างถึงบทย่อยการนำไปใช้งานที่โฮสต์โดยใช้มาตรฐาน C โดยไม่สนใจการดำรงอยู่ของบทที่ 5.1.2.1
Lundin

1
สิ่งที่น่าสังเกตเกี่ยวกับร่างมาตรฐาน C11 คือแม้ว่าfunc()จะถือว่าล้าสมัยแล้วร่างเองก็ใช้int main()ในตัวอย่างของตัวเอง
Antti Haapala

29

ส่งคืน 0 เมื่อสำเร็จและไม่ใช่ศูนย์สำหรับข้อผิดพลาด นี่เป็นมาตรฐานที่ใช้โดยการเขียนสคริปต์ UNIX และ DOS เพื่อค้นหาว่าเกิดอะไรขึ้นกับโปรแกรมของคุณ


8

main() ใน C89 และ K&R C ประเภทการคืนค่าที่ไม่ระบุค่าเริ่มต้นเป็น 'int'

return 1? return 0?
  1. หากคุณไม่ได้เขียนคำสั่ง return ในint main()การปิด{จะส่งกลับ 0 โดยค่าเริ่มต้น

  2. return 0หรือreturn 1จะได้รับจากกระบวนการหลัก main()ในเปลือกก็จะเข้าสู่ตัวแปรเปลือกและถ้าคุณกำลังเรียกใช้โปรแกรมของคุณในรูปแบบเปลือกและไม่ได้ใช้ตัวแปรที่แล้วคุณไม่จำเป็นต้องกังวลเกี่ยวกับค่าตอบแทนของ

ดูฉันจะได้รับสิ่งที่ฟังก์ชั่นหลักของฉันคืนได้อย่างไร .

$ ./a.out
$ echo $?

วิธีนี้คุณจะเห็นว่ามันเป็นตัวแปรซึ่งได้รับไบต์ที่สำคัญน้อยที่สุดของค่าตอบแทนของ$?main()

ในการเขียนสคริปต์ Unix และ DOS return 0ความสำเร็จและไม่เป็นศูนย์สำหรับข้อผิดพลาดจะถูกส่งคืน นี่คือมาตรฐานที่ใช้โดย Unix และ DOS scripting เพื่อค้นหาว่าเกิดอะไรขึ้นกับโปรแกรมของคุณและควบคุมการไหลทั้งหมด


4
การพูดอย่างเคร่งครัด$?ไม่ใช่ตัวแปรสภาพแวดล้อม เป็นตัวแปรเชลล์ (หรือบิวด์อิน) ที่กำหนดไว้ล่วงหน้า ความแตกต่างนั้นยากที่จะมองเห็น แต่ถ้าคุณเรียกใช้env(โดยไม่มีข้อโต้แย้ง) มันจะพิมพ์สภาพแวดล้อมและ$?จะไม่แสดงในสภาพแวดล้อม
Jonathan Leffler

1
การส่งคืน 0 โดยอัตโนมัติเมื่อ main "fall of the end" มีเฉพาะใน C ++ และ C99 เป็นต้นไปไม่ใช่ C90
Kaz

สะกดผิด "ปิด{" }ควรจะเป็น ดังนั้นฉันจะไม่อนุญาตให้แก้ไขขนาดเล็กนี้
Spencer

7

โปรดทราบว่าแม้ว่าคุณจะส่งคืนค่า int บาง OSes (Windows) จะตัดทอนค่าที่ส่งคืนเป็นไบต์เดียว (0-255)


4
Unix ทำเช่นเดียวกันเช่นเดียวกับระบบปฏิบัติการอื่น ๆ ฉันรู้ว่า VMS ทำสิ่งที่แปลกประหลาดอย่างเหลือเชื่อด้วยการส่งคืนสิ่งอื่นนอกเหนือจาก EXIT_SUCCESS หรือ EXIT_FAILURE กำลังขอปัญหา
Leon Timmermans

2
MSDN จะต่างกัน: เมื่อรายงานผ่าน mscorlib รหัสทางออกจะเป็นจำนวนเต็ม 32 บิตที่ลงนามแล้ว นี่ดูเหมือนจะบอกเป็นนัย ๆ ว่าไลบรารีรันไทม์ Cที่ตัดทอนรหัสออกมีข้อบกพร่อง

ใช่มันไม่ถูกต้อง ใน Windows จะมีการส่งคืนจำนวนเต็ม 32 บิต (และแปลงเป็นunsigned) สิ่งนี้จะเหมือนกันในระบบ UNIX ที่มีจำนวนเต็ม 32 บิต แต่เชลล์สไตล์ UNIX บนระบบใดระบบหนึ่งโดยทั่วไปจะเก็บจำนวนเต็ม 8 บิตที่ไม่ได้ลงชื่อ
John McFarlane

4

ระบบปฏิบัติการสามารถใช้ค่าส่งคืนเพื่อตรวจสอบว่าโปรแกรมปิดอย่างไร

ค่าส่งกลับ 0 มักจะหมายถึงตกลงในระบบปฏิบัติการส่วนใหญ่ (สิ่งที่ฉันคิดต่อไป)

นอกจากนี้ยังสามารถตรวจสอบได้เมื่อคุณเรียกใช้กระบวนการด้วยตัวเองและดูว่าโปรแกรมออกและดำเนินการอย่างถูกต้องหรือไม่

มันไม่ใช่แค่การเขียนโปรแกรมแบบแผน


ไม่มีอะไรในคำถามที่บ่งบอกว่ามีระบบการผ่าตัดอยู่ การคืนค่าไม่สมเหตุสมผลในระบบอิสระ
Lundin

3

ค่าตอบแทนของmain()แสดงให้เห็นว่าโปรแกรมออกจาก หากค่าส่งคืนzeroหมายความว่าการดำเนินการสำเร็จในขณะที่ค่าที่ไม่เป็นศูนย์ใด ๆ จะแสดงว่ามีบางสิ่งไม่ดีในการดำเนินการ


1
นี่คือความคิดเห็นไม่ใช่คำตอบสำหรับคำถาม
Lundin

2

ฉันอยู่ภายใต้ความประทับใจที่มาตรฐานระบุว่าหลักไม่ต้องการค่าส่งคืนเนื่องจากการส่งคืนที่ประสบความสำเร็จนั้นขึ้นอยู่กับระบบปฏิบัติการ (ศูนย์หนึ่งอาจจะประสบความสำเร็จหรือล้มเหลวในอีก) ดังนั้นการไม่มีตัวตนกลับมาเป็นสัญญาณสำหรับ คอมไพเลอร์เพื่อแทรกการกลับมาสำเร็จ

อย่างไรก็ตามฉันมักจะกลับ 0


C99 (และ C ++ 98) ช่วยให้คุณสามารถข้ามคำสั่งส่งคืนจากหลัก; C89 ไม่อนุญาตให้คุณข้ามข้อความสั่งคืน
Jonathan Leffler

นี่คือความคิดเห็นไม่ใช่คำตอบ
Lundin

สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม หากต้องการวิจารณ์หรือขอคำชี้แจงจากผู้แต่งโปรดแสดงความคิดเห็นใต้โพสต์ของพวกเขา
Steve Lillis

6
@SteveLillis: ในปี 2008 ดังนั้นไม่มีส่วนความคิดเห็น
graham.reeds

2

การส่งคืน 0 ควรบอกโปรแกรมเมอร์ว่าโปรแกรมทำงานเสร็จสมบูรณ์แล้ว


การคืนค่า 1 จากmain()สัญญาณปกติจะเกิดข้อผิดพลาด ส่งคืน 0 สัญญาณสำเร็จ หากโปรแกรมของคุณล้มเหลวเสมอ 1 แสดงว่าไม่เป็นความคิดที่ดีที่สุด
Jonathan Leffler

1
@JonathanLeffler: ความหมายของการกลับมา1จากmainการใช้งานที่กำหนดไว้ ค่าเพียงภาษาที่กำหนดไว้จะ0, EXIT_SUCCESS(มักจะกำหนดให้เป็น0) EXIT_FAILUREและ ใน OpenVMS return 1;หมายถึงการยกเลิกสำเร็จ
Keith Thompson

VMS ไม่ใช่ 'ปกติ' - ในความหมายของสิ่งที่ฉันพูด ไม่ใช่สิ่งที่ต้องการ 'คุณค่าแปลก ๆ ใด ๆ ที่ประสบความสำเร็จ แม้ค่าจะล้มเหลว 'บน VMS?
Jonathan Leffler

2

ละเว้น return 0

เมื่อ C หรือ C ++ โปรแกรมมาถึงจุดสิ้นสุดของmainคอมไพเลอร์จะสร้างรหัสโดยอัตโนมัติเพื่อกลับ 0, ดังนั้นจึงไม่มีความจำเป็นต้องใส่อย่างชัดเจนในตอนท้ายของ return 0;main

หมายเหตุ:เมื่อฉันทำตามคำแนะนำนี้เกือบจะตามมาด้วยความคิดเห็นอย่างใดอย่างหนึ่งจากสองประเภท: "ฉันไม่ทราบ" หรือ "นั่นคือคำแนะนำที่ไม่ดี!" เหตุผลของฉันคือมันปลอดภัยและมีประโยชน์ในการพึ่งพาพฤติกรรมคอมไพเลอร์ที่สนับสนุนโดยมาตรฐาน สำหรับ C ตั้งแต่ C99; ดูที่ ISO / IEC 9899: 1999 ส่วน 5.1.2.2.3:

[... ] การคืนค่าจากการเรียกเริ่มต้นไปยังmainฟังก์ชันเทียบเท่ากับการเรียกexitฟังก์ชันที่มีค่าที่ส่งคืนโดยmainฟังก์ชันเป็นอาร์กิวเมนต์ ถึงการ}ที่ยุติmainฟังก์ชั่นส่งกลับค่า 0

สำหรับ C ++ ตั้งแต่มาตรฐานแรกในปี 1998 ดู ISO / IEC 14882: 1998 ส่วน 3.6.1:

หากการควบคุมมาถึงจุดสิ้นสุดของ main โดยไม่พบคำสั่ง return ผลลัพธ์ที่ได้คือการดำเนินการ return 0

มาตรฐานทั้งสองรุ่นตั้งแต่นั้นมา (C99 และ C ++ 98) ได้รักษาแนวคิดเดิมไว้ เราพึ่งพาฟังก์ชั่นสมาชิกที่สร้างขึ้นโดยอัตโนมัติใน C ++ และมีเพียงไม่กี่คนที่เขียนreturn;คำสั่งที่ชัดเจนในตอนท้ายของvoidฟังก์ชั่น เหตุผลที่ไม่ถนัดดูเหมือนจะต้มลงไป"มันดูแปลก ๆ" ถ้าเช่นฉันคุณอยากรู้เกี่ยวกับเหตุผลของการเปลี่ยนแปลงมาตรฐาน C อ่านคำถามนี้ โปรดทราบด้วยว่าในช่วงต้นปี 1990 สิ่งนี้ถูกพิจารณาว่าเป็น "การฝึกอย่างเลอะเทอะ" เพราะมันเป็นพฤติกรรมที่ไม่ได้กำหนด (แม้ว่าจะสนับสนุนอย่างกว้างขวาง) ในเวลานั้น

นอกจากนี้หลักเกณฑ์หลักของC ++ จะมีการละเว้นหลายอินสแตนซ์return 0;เมื่อสิ้นสุดmainและไม่มีอินสแตนซ์ที่เขียนผลตอบแทนชัดเจน แม้ว่าจะยังไม่มีแนวทางที่เฉพาะเจาะจงในหัวข้อนี้โดยเฉพาะในเอกสารดังกล่าว แต่อย่างน้อยก็ดูเหมือนเป็นการรับรองการปฏิบัติโดยปริยาย

ดังนั้นฉันจึงสนับสนุนให้ละเว้นมัน คนอื่นไม่เห็นด้วย (มักโกรธ!) ไม่ว่าในกรณีใดถ้าคุณพบโค้ดที่ไม่ใช้คุณจะรู้ว่ามันสนับสนุนมาตรฐานอย่างชัดเจนและคุณจะรู้ว่ามันหมายถึงอะไร


2
นี่เป็นคำแนะนำที่ไม่ดีเพราะคอมไพเลอร์ที่ใช้ C89 เท่านั้นไม่ใช่มาตรฐานในภายหลังยังคงเป็นเรื่องธรรมดามาก (ฉันเขียนสิ่งนี้ในปี 2560) และจะยังคงเป็นเรื่องธรรมดามากสำหรับอนาคตอันใกล้ ตัวอย่างเช่นล่าสุดฉันตรวจสอบว่าไม่มีคอมไพเลอร์ของ Microsoft ที่ติดตั้ง C99 และฉันเข้าใจว่านี่เป็นเรื่องปกติสำหรับคอมไพเลอร์ระบบฝังตัวที่ไม่ใช่ GCC
zwol

4
@zwol: ใครก็ตามที่ไม่มีทางเลือกนอกจากใช้คอมไพเลอร์ที่ล้าสมัย 28 ปีอาจมีปัญหามากกว่าการตัดสินใจว่าจะรวมไว้อย่างชัดเจนreturn 0;แต่ฉันจะสังเกตว่าคอมไพเลอร์ในยุคนั้นก็ใช้งานปริยายreturn 0;เหมือนกัน มาตรฐาน
Edward

2
ที่จริงแล้วฉันใช้ระบบฝังตัวจำนวนมากทำงานและไม่พบคอมไพเลอร์ที่ไม่สนับสนุนการใช้งานโดยนัยreturn 0มานานกว่าทศวรรษ ยังมีรุ่นปัจจุบันของ Microsoft C สนับสนุนเป็นอย่างดี ข้อมูลของคุณล้าสมัยหรือไม่
Edward

2
ฉันรู้สึกซาบซึ้งที่สิ่งนี้ขัดแย้งใน C เกือบ (ต่อ @zwol) ใน C ++ การโต้เถียงรอบ ๆ นี่เป็นเรื่องไร้สาระ
Lightness Races ที่ Orbit

2
@ เอ็ดเวิร์ดฉันไม่ได้บอกว่าไม่มีการโต้เถียงฉันบอกว่ามันไร้สาระ: P
Lightness Races ใน Orbit

1

สิ่งที่จะส่งคืนนั้นขึ้นอยู่กับสิ่งที่คุณต้องการจะทำอย่างไรกับสิ่งที่เรียกได้ ตัวอย่างเช่นถ้าคุณกำลังใช้โปรแกรมของคุณด้วยเชลล์บรรทัดคำสั่งคุณต้องส่งคืน 0 สำหรับความสำเร็จและไม่ใช่ศูนย์สำหรับความล้มเหลว จากนั้นคุณจะสามารถใช้โปรแกรมในเชลล์ด้วยการประมวลผลแบบมีเงื่อนไขขึ้นอยู่กับผลลัพธ์ของโค้ดของคุณ นอกจากนี้คุณสามารถกำหนดค่าที่ไม่เป็นศูนย์ใด ๆ ตามการตีความของคุณตัวอย่างเช่นสำหรับข้อผิดพลาดที่สำคัญจุดออกจากโปรแกรมที่แตกต่างกันสามารถยกเลิกโปรแกรมที่มีค่าการออกที่แตกต่างกันและที่เชลล์โทรเรียกซึ่งสามารถตัดสินใจได้ว่าจะทำอย่างไร หากรหัสไม่ได้มีไว้สำหรับใช้กับเชลล์และค่าที่ส่งคืนไม่รบกวนใครก็อาจถูกละเว้น ฉันใช้ลายเซ็นส่วนตัวint main (void) { .. return 0; .. }


รูปแบบของ main () ถูกกำหนดโดยการนำไปใช้ซึ่งหมายถึงคอมไพเลอร์ โปรแกรมเมอร์ไม่ได้เลือกรูปแบบที่จะเลือกยกเว้นเมื่อคอมไพเลอร์รองรับหลายรูปแบบ
Lundin

@Lundin ชนิดส่งคืนจะถูกนำไปใช้โดยการนำไปใช้ แต่ค่าที่จะส่งคืนจะถูกตัดสินโดยโปรแกรมเมอร์ C99 มาตรา 5.1.2.2.3 กล่าวว่าประเภทของการกลับมาของเข้ากันได้กับmain intดังนั้นการกลับมาintจะไม่เป็นปัญหา แม้ว่าอนุญาตให้ส่งคืนชนิดอื่นได้ แต่ในกรณีนั้นตัวแปรสภาพแวดล้อมที่มีค่าส่งคืนจะไม่ได้รับการระบุ แต่ถ้าโปรแกรมเมอร์ทำreturn 0;ใน bash มันสามารถใช้ทำกิ่งไม้ได้
phoxis

1

หากคุณมีปัญหาที่เกี่ยวข้องกับประสิทธิภาพในการส่งคืนจำนวนเต็มจากกระบวนการคุณควรหลีกเลี่ยงการเรียกกระบวนการนั้นหลายครั้งว่าค่าที่ส่งคืนนี้กลายเป็นปัญหา

หากคุณกำลังทำเช่นนี้ (เรียกใช้กระบวนการหลายครั้ง) คุณควรหาวิธีที่จะวางตรรกะของคุณโดยตรงในผู้โทรหรือในไฟล์ DLL โดยไม่ต้องจัดสรรกระบวนการเฉพาะสำหรับการโทรแต่ละครั้ง การจัดสรรหลายขั้นตอนทำให้คุณมีปัญหาประสิทธิภาพที่เกี่ยวข้องในกรณีนี้

ในรายละเอียดหากคุณต้องการทราบว่าการคืนค่า 0 นั้นมีประสิทธิภาพมากกว่าหรือน้อยกว่าการคืนค่า 1 อาจขึ้นอยู่กับคอมไพเลอร์ในบางกรณี แต่โดยทั่วไปสมมติว่าพวกเขาอ่านจากแหล่งเดียวกัน (local, field, constant, embedded) ในโค้ด, ผลการทำงาน, ฯลฯ ) มันต้องการจำนวนรอบสัญญาณนาฬิกาที่เท่ากันทุกประการ


1

นี่คือตัวอย่างเล็ก ๆ ของการใช้รหัสส่งคืน ...

เมื่อใช้เครื่องมือต่าง ๆ ที่เทอร์มินัล Linux จัดหาให้สามารถใช้โค้ดส่งคืนเช่นการจัดการข้อผิดพลาดหลังจากกระบวนการเสร็จสมบูรณ์ ลองจินตนาการว่า myfile ไฟล์ข้อความต่อไปนี้มีอยู่:

นี่คือตัวอย่างบางส่วนเพื่อตรวจสอบว่า grep ทำงานอย่างไร

เมื่อคุณดำเนินการคำสั่ง grep กระบวนการจะถูกสร้างขึ้น เมื่อผ่าน (และไม่หยุด) จะส่งคืนรหัสบางส่วนระหว่าง 0 ถึง 255 ตัวอย่างเช่น:

$ grep order myfile

ถ้าคุณทำ

$ echo $?
$ 0

คุณจะได้ 0 ทำไม เนื่องจากgrepพบการจับคู่และส่งคืนรหัสออก 0 ซึ่งเป็นค่าปกติสำหรับการออกจากการสำเร็จ ลองตรวจสอบอีกครั้ง แต่มีบางอย่างที่ไม่ได้อยู่ในไฟล์ข้อความของเราดังนั้นจึงไม่พบข้อมูลที่ตรงกัน:

$ grep foo myfile
$ echo $?
$ 1

เนื่องจาก grep ไม่สามารถจับคู่โทเค็น "foo" กับเนื้อหาของไฟล์ของเรารหัสส่งคืนคือ 1 (นี่เป็นกรณีปกติเมื่อเกิดความล้มเหลว แต่ตามที่ระบุไว้ข้างต้นคุณมีค่ามากมายให้เลือก)

ตอนนี้สคริปต์ทุบตีต่อไปนี้ (เพียงพิมพ์ใน terminal Linux) แม้ว่าขั้นพื้นฐานมากควรให้ความคิดของการจัดการข้อผิดพลาด:

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

หลังจากบรรทัดที่สองไม่มีอะไรถูกพิมพ์ไปยังเทอร์มินัลตั้งแต่ "foo" ได้ทำการส่งคืน grep 1 และเราตรวจสอบว่าโค้ดส่งคืนของ grep เท่ากับ 0 คำสั่งเงื่อนไขที่สองสะท้อนข้อความในบรรทัดสุดท้ายเพราะมันเป็นจริงเนื่องจาก CHECK == 1

ในขณะที่คุณสามารถดูว่าคุณกำลังเรียกสิ่งนี้หรือไม่และกระบวนการนั้นบางครั้งก็เป็นสิ่งจำเป็นที่จะต้องดูว่ามันส่งคืนอะไรบ้าง (โดยค่าส่งคืนของ main ())


ในเชลล์สคริปต์คุณต้องใช้if grep foo myfile; then echo 'Match found'; else echo 'No match was found'; fi- ทดสอบสถานะการส่งคืนโดยตรง ถ้าคุณต้องการบันทึกสถานะ (สำหรับการรายงานและอื่น ๆ ) แสดงว่าคุณใช้การมอบหมาย คุณอาจใช้if grep foo myfile; CHECK=$?; [ "$CHECK" = 0 ]; then echo 'Match found'; else echo 'No match was found'; fiหรือคุณอาจใช้สามบรรทัด คุณอาจใช้ตัวเลือก-sและ-qเพื่อgrepป้องกันการจับคู่หรือข้อความแสดงข้อผิดพลาดตามปกติ อย่างไรก็ตามนี่คือเชลล์ minutiae - จุดสำคัญที่สถานะทางออกมีประโยชน์ - ก็โอเค
Jonathan Leffler

1

อะไรคือวิธีที่ถูกต้อง (มีประสิทธิภาพมากที่สุด) ในการกำหนดฟังก์ชั่น main () ใน C และ C ++ - int main () หรือ void main () - และทำไม?

คำเหล่านั้น "(มีประสิทธิภาพมากที่สุด)" ไม่เปลี่ยนคำถาม ถ้าคุณอยู่ในสภาพแวดล้อมที่เป็นอิสระมีหนึ่งวิธีที่ถูกต้องในระดับสากลที่จะประกาศmain()และที่เป็นกลับ int

สิ่งที่ควรmain()กลับมาใน C และ C ++

มันไม่ใช่สิ่งที่ควรจะ main()คืน แต่เป็นสิ่งที่จะ main()กลับมา main()แน่นอนว่าเป็นฟังก์ชั่นที่คนอื่นเรียก คุณไม่สามารถควบคุมรหัสที่โทรออกmain()ได้ ดังนั้นคุณต้องประกาศmain()พร้อมลายเซ็นประเภทที่ถูกต้องเพื่อให้ตรงกับผู้โทร คุณไม่มีทางเลือกในเรื่องนี้ คุณไม่ต้องถามตัวเองว่าอะไรจะมีประสิทธิภาพมากขึ้นหรือน้อยลงหรือสไตล์ที่ดีขึ้นหรือแย่ลงหรืออะไรแบบนั้นเพราะคำตอบนั้นถูกนิยามไว้อย่างสมบูรณ์แล้วสำหรับคุณโดยมาตรฐาน C และ C + เพียงแค่ติดตามพวกเขา

ถ้า int main () แล้วส่งคืน 1 หรือคืน 0

0 สำหรับความสำเร็จไม่ใช่ศูนย์สำหรับความล้มเหลว ไม่ใช่สิ่งที่คุณต้องเลือก (หรือไป): มันถูกกำหนดโดยส่วนต่อประสานที่คุณควรจะทำตาม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.