ทำไม `main` ไม่สามารถคืนค่า double หรือ String แทน int หรือ void ได้


38

ในหลายภาษาเช่น C, C ++ และ Java ที่mainวิธีการ / ฟังก์ชั่นมีประเภทการกลับมาของvoidหรือintแต่ไม่ได้หรือdouble Stringอะไรคือเหตุผลเบื้องหลัง

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

ดังนั้นคำถามของฉันคือ: ทำไมmainมีลายเซ็นประเภทที่มีและไม่แตกต่างกันอย่างไร


15
ค่าตอบแทนสองเท่าหมายถึงอะไร ค่าส่งคืนสตริงหมายความว่าอย่างไร

1
ki เข้าใจว่ามันไม่ได้มีความหมายอะไรเลย แต่ด้วยเหตุผลและอนุสัญญาอื่น ๆ ?
JAVA

1
ฉันคิดว่ามันไม่ได้มีความหมายอะไรเลยเพราะในระดับสากลก็เลือกที่ 0 สำหรับทางออกปกติและไม่ใช่ศูนย์สำหรับความผิดปกติ int ได้รับเลือกเป็นประเภทข้อมูลที่ง่ายที่สุดพร้อมความเข้ากันได้กับภาษาไขว้กว้าง @ delnan
JAVA

@sunny จากสิ่งที่ฉันสามารถรวบรวมจากประสบการณ์ของฉันกับ Unix-like OSs, 0 ถูกใช้เป็น "exit ปกติ" (0 ข้อผิดพลาด) เพราะมันไม่ชัดเจนเมื่อเปรียบเทียบกับค่าจำนวนเต็มอื่น ๆ เนื่องจากภาษาสมัยใหม่ส่วนใหญ่ (ไม่ใช่ทั้งหมด) ได้รับการออกแบบให้คล้ายกับ (ถ้าไม่ได้ออกแบบที่ด้านหลัง) C และเนื่องจาก C ถูกใช้ในการเขียน Unix ฉันจึงบอกว่ามันเป็นการตัดสินใจทางประวัติศาสตร์ของ KNR
Jamie Taylor

3
@sunny "การใช้งานร่วมกันได้หลากหลายภาษา" ไม่เป็นปัญหา C และ UNIX ถูกเขียนควบคู่ เหตุผลที่ภาษาอื่น ๆ กลับมา ints ก็เพราะพวกเขาถูกออกแบบมาเพื่อทำงานในสภาพแวดล้อมที่เหมือน UNIX หรือ UNIX

คำตอบ:


83

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

หากนี่คือสตริงการตอบสนองจะยากในภาษาต่าง ๆ internals ของสตริง Pascal (ไบต์แรกคือความยาว) และสตริง FORTRAN (คงที่, เพิ่มเป็นค่าบางส่วน) และสตริง C (สิ้นสุด null) จะแตกต่างกันทั้งหมด สิ่งนี้จะทำให้การคืนค่าสอดคล้องกับระบบปฏิบัติการที่ท้าทาย สมมติว่าสิ่งนี้ได้รับการแก้ไขคุณจะทำอย่างไรเพื่อตอบคำถามที่ระบบปฏิบัติการมีของโปรแกรม การเปรียบเทียบสตริงจะเต็มไปด้วยข้อผิดพลาด ("ความสำเร็จ" และ "ความสำเร็จ") และในขณะที่ข้อผิดพลาดอาจมีประโยชน์กับมนุษย์มากขึ้นมันเป็นเรื่องยากสำหรับระบบปฏิบัติการหรือโปรแกรมอื่น (เชลล์) ที่จะจัดการกับ นอกจากนี้ยังมีความแตกต่างอย่างมีนัยสำคัญแม้ในตัวสตริงเอง - EBCDIC (พร้อมกับโค้ดเพจทั้งหมด) เทียบกับ ASCII

ลอยและคู่ไม่มีค่าเพิ่มเติมสำหรับจำนวนเต็มสำหรับการสื่อสารข้อมูลกลับไปยังระบบปฏิบัติการ (และเชลล์) ส่วนใหญ่ไม่มีส่วนใดส่วนหนึ่งของคอมพิวเตอร์ที่ใช้จัดการกับตัวเลขทศนิยม คู่ยังไม่นับทำให้การเปรียบเทียบยาก ไม่นับรวมพวกเขาทำการรายงานว่าเกิดข้อผิดพลาดอะไร (สมมติว่าคุณเลือกค่าเฉพาะเพื่อความสำเร็จ) อีกครั้งจุดลอยตัวไม่สอดคล้องกัน - การลอยบนเครื่อง 8 บิตแตกต่างจากการลอยในเครื่อง 16 บิตและ 32 บิต (และนั่นเป็นเพียง 'ปกติ' - แม้แต่ใน IBM จุดลอยตัวไม่ได้มาตรฐาน ระหว่างเครื่องจักรโดยผู้ผลิตรายเดียวกันจนถึงปี 1980) จากนั้นคุณก็มีคอมพิวเตอร์ทศนิยมกับฐานสอง ค่าจุดลอยตัวไม่สอดคล้องกันและไม่ให้ข้อมูลที่มีความหมายกลับมา

นั่นทำให้เรามีตัวเลือกไบต์และจำนวนเต็ม การประชุมที่ก่อตั้งขึ้นคือ '0' ประสบความสำเร็จและสิ่งอื่นใดเป็นข้อผิดพลาด จำนวนเต็มให้พื้นที่มากกว่าไบต์สำหรับการรายงานข้อผิดพลาด สามารถระบุได้ (การส่งคืน 1 หมายถึง XYZ, ส่งคืน 2 หมายถึง ABC, ส่งคืน 3, หมายถึง DEF, ฯลฯ .. ) หรือใช้เป็นธง ( 0x0001หมายถึงสิ่งนี้ล้มเหลว, 0x0002หมายความว่าล้มเหลว, 0x0003หมายถึงล้มเหลว การ จำกัด สิ่งนี้ให้เพียงไบต์เดียวอาจหมดแฟล็กได้อย่างง่ายดาย (เพียง 8) ดังนั้นการตัดสินใจอาจใช้จำนวนเต็ม


2
ฉันคิดว่า main ถูกเรียกใช้โดยไลบรารีรันไทม์ c / c ++ ก่อนที่ os จะเรียกมันว่าซึ่งเป็นส่วนหนึ่งของรหัสที่โหลดพร้อมกับรหัสของเราและเรียกโดย os @ MichaelT
JAVA

5
main()ถูกเรียกใช้วิธีต่างๆในระบบปฏิบัติการที่แตกต่างกัน ใน C วิธีการหลัก () วิธีการเริ่มต้นเรียกว่าอย่างไร เข้าไปในนี้

22
ฉันคิดว่าประเด็นสำคัญที่ต้องเข้าใจคือmain- ไม่เหมือนกับฟังก์ชั่นอื่น ๆ ในโปรแกรมใด ๆ - ไม่ใช่ส่วนหนึ่งของโปรโตคอลที่กำหนดโดยโปรแกรมเมอร์ แต่โปรโตคอลที่ใช้เชื่อมต่อกับโฮสต์ (OS) คุณไม่ได้เลือกเพราะคุณไม่เคยเลือก ในระดับที่สามารถนำไปปฏิบัติได้มากขึ้น UNIX คาดว่า int จะถูกส่งคืนโดยกระบวนการดังนั้นโปรโตคอล C-to-UNIX จึงทำเช่นนั้น อาร์กิวเมนต์แบบอะนาล็อกสามารถสร้างขึ้นเพื่อส่งผ่านข้อโต้แย้ง: หาก C ถูกประดิษฐ์ขึ้นสำหรับ OS / โฮสต์ที่ส่งผ่านตัวเลขเท่านั้นเป็นอาร์กิวเมนต์ (เช่นไม่มีบรรทัดคำสั่ง) อาร์กิวเมนต์จะเป็น ints แทนสตริง
Euro Micelli

2
IBM นำแนวคิดของโค้ดเพจจาก EBCDIC ไปยังพีซี พวกเขายังคงหลอกหลอนเราในวันนี้ 35 ปีหลังจากเปิดตัว IBM 5150 ASCII 7 บิตนั้นไม่มีรหัสเพจ แต่รหัสอักขระ 8 บิตสามารถตีความได้หลายวิธีแม้กระทั่งบนคอมพิวเตอร์เครื่องเดียวขึ้นอยู่กับการตั้งค่า - - นับประสา codepages ที่รหัสสำหรับการเข้ารหัสหลายไบต์ ดังนั้นมันยิ่งกว่าสิ่งที่คุณพูดถึงในประโยคสุดท้ายของย่อหน้าที่สอง
CVn

@EuroMicelli ที่เป็นข้อมูลที่ดีมากจริง ๆ ขอบคุณสำหรับ :) ว่า
JAVA

27

ดีก็สามารถทำได้

ตัวอย่างเช่นในภาษาถิ่นของ C ที่ใช้ในระบบปฏิบัติการPlan 9mainโดยปกติแล้วจะประกาศเป็นvoidฟังก์ชัน แต่สถานะการออกจะถูกส่งกลับไปยังสภาพแวดล้อมการโทรโดยส่งตัวชี้สตริงไปยังexits()ฟังก์ชัน สตริงว่างหมายถึงความสำเร็จและสตริงที่ไม่ว่างใด ๆ แสดงถึงความล้มเหลวบางประเภท สิ่งนี้สามารถนำไปใช้งานได้โดยmainส่งคืนchar*ผลลัพธ์

และแน่นอนว่ามันจะเป็นไปได้ที่จะใช้ระบบที่มีfloatหรือdoubleออกจากสถานะ

แล้วทำไมintล่ะ มันเป็นเพียงเรื่องของการประชุม - และมีคุณค่าอย่างมากในการมีระบบปฏิบัติการและโปรแกรมที่ทำงานภายใต้พวกเขาปฏิบัติตามแบบแผนทั่วไป

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

จุดลอยตัวจะเป็นแบบแผนที่ยากขึ้นเพราะ (ก) การสนับสนุนจุดลอยตัวนั้นไม่เป็นสากล (b) มันยากกว่าในการกำหนดการแมประหว่างค่าจุดลอยตัวกับเงื่อนไขข้อผิดพลาด (c) ระบบที่แตกต่างกันใช้จุดลอยตัวที่แตกต่างกัน การเป็นตัวแทนจุดและ (d) เพียงแค่จินตนาการถึงความสนุกในการติดตามข้อผิดพลาดในการปัดเศษในสถานะออกจากโปรแกรมของคุณ ในทางกลับกันจำนวนเต็มยืมตัวเองดีมากในการระบุรหัสข้อผิดพลาด

ตามที่ฉันกล่าวถึงแผน 9 ใช้สตริง แต่มีความซับซ้อนบางอย่างสำหรับการจัดการหน่วยความจำการเข้ารหัสอักขระ ฯลฯ เท่าที่ฉันรู้ความคิดใหม่เมื่อแผน 9 นำไปใช้และไม่ได้แทนที่สิ่งที่มีอยู่เดิม อนุสัญญาอย่างกว้างขวาง

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


9

ค่าที่ส่งคืนโดยเมธอดหลักคือ "exit code" มันถูกใช้โดยแอปพลิเคชันผู้โทร (โดยปกติทุบตี) เพื่อทดสอบว่าโปรแกรมสิ้นสุดลงตามที่คาดไว้หรือไม่ การคืนค่าจำนวนเต็มเป็นวิธีที่ง่ายที่สุดในการดำเนินการในระดับระบบปฏิบัติการ Double ไม่สมเหตุสมผลสำหรับรหัสข้อผิดพลาดและ String นั้นยากที่จะรักษาในระดับ OS (ไม่มี GC)


3
เหตุใดจึงต้องมีการรวบรวมสตริงขยะในขณะที่จำนวนเต็มไม่?
แบรด

4
@Brad, สตริงมีความยาวผันแปรได้และจะเป็นสาระสำคัญเหมือนกับการส่งกลับอาร์เรย์ซึ่งอาจเป็นอักขระหนึ่งตัวหรืออาจเป็นพันก็ได้ หน่วยความจำแบบไดนามิกจะเจ็บปวดในขณะที่ int เป็นขนาดที่ค่อนข้างคงที่ซึ่งไม่ยากที่จะจัดการ
JB King
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.