Tại sao `main` không thể trả về một chuỗi kép hoặc Chuỗi thay vì int hoặc void?


38

Trong nhiều ngôn ngữ như C, C ++ và Java, mainphương thức / hàm có kiểu trả về voidhoặc int, nhưng không doublehoặc String. Điều gì có thể là lý do đằng sau đó?

Tôi biết một chút rằng chúng ta không thể làm điều đó bởi vì mainđược gọi bởi thư viện thời gian chạy và nó mong đợi một số cú pháp giống như vậy int main()hoặc int main(int,char**)chúng ta phải tuân theo điều đó.

Vì vậy, câu hỏi của tôi là: tại sao maincó chữ ký loại mà nó có, mà không phải là một chữ ký khác?


15
Giá trị trả lại gấp đôi có nghĩa là gì? Giá trị trả về chuỗi có nghĩa là gì?

1
ki hiểu rằng nó không có nghĩa gì cả. Nhưng có lý do và quy ước nào khác không?
JAVA

1
Tôi nghĩ nó không có nghĩa gì cả, đơn giản vì trên toàn cầu, nó được chọn là 0 cho lối ra bình thường và khác không cho bất thường. Một int được chọn là loại dữ liệu đơn giản nhất có khả năng tương thích ngôn ngữ rộng. @ delnan
JAVA

@sunny Từ những gì tôi có thể thu thập được từ trải nghiệm của mình với các HĐH giống Unix, 0 được sử dụng như một "lối thoát thông thường" (0 lỗi) vì nó không rõ ràng khi so sánh với các giá trị nguyên khác. Vì hầu hết (không phải tất cả) các ngôn ngữ hiện đại được thiết kế tương tự (nếu không được thiết kế ở mặt sau) C và vì C được sử dụng để viết Unix, nên tôi nói đó là một quyết định lịch sử của KnR.
Jamie Taylor

3
@sunny "khả năng tương thích ngôn ngữ rộng" không phải là vấn đề. C và UNIX đã được viết song song. Lý do nhiều ngôn ngữ khác trả về int là vì chúng được thiết kế để hoạt động trong môi trường giống như UNIX hoặc UNIX.

Câu trả lời:


83

Giá trị trả về của mainsẽ được chuyển đến hệ điều hành ( bất kỳ hệ điều hành nào ) theo một cách duy nhất, nhất quán. Thông tin mà hệ điều hành cần biết là "chương trình đã kết thúc thành công hay có lỗi?"

Nếu đây là một chuỗi, phản hồi trở nên khó khăn trong các ngôn ngữ khác nhau. Các phần bên trong của chuỗi Pascal (byte đầu tiên là chiều dài) và chuỗi FORTRAN (cố định, được đệm theo một số giá trị) và chuỗi C (kết thúc null) đều khác nhau. Điều này sẽ khiến việc trả về một giá trị phù hợp cho hệ điều hành đầy thách thức. Giả sử rằng điều này đã được giải quyết, bạn sẽ làm gì để trả lời câu hỏi mà HĐH có của chương trình? So sánh chuỗi có nhiều lỗi ("thành công" so với "Thành công") và trong khi lỗi có thể hữu ích hơn với con người, thì hệ điều hành hoặc chương trình (vỏ) khác khó xử lý hơn. Cũng có sự khác biệt đáng kể ngay cả trong chính chuỗi - EBCDIC (với tất cả các trang mã của nó) so với ASCII.

Phao và đôi cung cấp không có giá trị bổ sung trên số nguyên để truyền dữ liệu trở lại hệ điều hành (và hệ vỏ). Đối với hầu hết các phần, cả hai phần này của máy tính đều không xử lý các số dấu phẩy động. Nhân đôi cũng không phải là vô số khiến việc so sánh trở nên khó khăn. Không thể đếm được, họ báo cáo lỗi là gì (giả sử bạn đã chọn một giá trị cụ thể để thành công). Một lần nữa, các điểm nổi không nhất quán - một dấu phẩy trên máy 8 bit khác với dấu phẩy trên máy 16 bit và 32 bit (và đó là những điểm 'bình thường' - ngay cả trong IBM, điểm nổi không được chuẩn hóa giữa các máy của cùng một nhà sản xuất cho đến những năm 1980). Và sau đó bạn đã có số thập phân so với máy tính nhị phân. Các giá trị dấu phẩy động không nhất quán và không cung cấp dữ liệu có ý nghĩa trở lại.

Điều đó thực sự để lại cho chúng ta các byte và số nguyên dưới dạng tùy chọn. Quy ước được thành lập là "0" là thành công và bất cứ điều gì khác là một lỗi. Một số nguyên cung cấp nhiều chỗ hơn một byte để báo cáo lỗi. Nó có thể được liệt kê (trả về 1 có nghĩa là XYZ, trả về 2 có nghĩa là ABC, trả về 3, có nghĩa là DEF, v.v.) hoặc được sử dụng làm cờ ( 0x0001có nghĩa là thất bại, 0x0002có nghĩa là thất bại, 0x0003có nghĩa là thất bại và cả thất bại). Giới hạn này chỉ là một byte có thể dễ dàng hết cờ (chỉ 8), vì vậy quyết định có lẽ là sử dụng một số nguyên.


2
Tôi nghĩ rằng main được gọi bởi thư viện thời gian chạy c / c ++ trước khi os gọi nó cũng là một đoạn mã được tải cùng với mã của chúng tôi và được gọi bởi os @ MichaelT
JAVA

5
main()được gọi theo nhiều cách khác nhau trên các hệ điều hành khác nhau. Trong C, phương thức main () ban đầu được gọi như thế nào? đi sâu vào vấn đề này

22
Tôi nghĩ rằng điểm quan trọng cần hiểu là main- không giống như các chức năng khác trong bất kỳ chương trình nào - không phải là một phần của giao thức được xác định bởi lập trình viên, mà là giao thức được sử dụng để giao tiếp với máy chủ (HĐH). Bạn không được chọn vì nó không bao giờ là của bạn để chọn. Ở mức độ thực dụng hơn, UNIX mong muốn một int được trả về bởi một tiến trình và vì vậy giao thức C-to-UNIX thực hiện chính xác điều đó. Một đối số tương tự có thể được tạo để truyền đối số: nếu C đã được phát minh cho một hệ điều hành / máy chủ chỉ truyền các số dưới dạng đối số (ví dụ: không có dòng lệnh), thì các đối số sẽ là ints thay vì chuỗi.
Euro Micelli

2
IBM đã lấy khái niệm về các trang mã từ EBCDIC cho PC của họ. Họ vẫn còn ám ảnh chúng ta hôm nay, xảy ra 35 năm sau sự ra đời của IBM 5150. 7-bit ASCII là bảng mã-ít hơn, nhưng mã 8-bit nhân vật có thể được giải thích theo nhiều cách khác nhau ngay cả trên một máy tính duy nhất, tùy thuộc vào các thiết lập - - hãy để một mình các bộ mã mà mã hóa cho nhiều byte. Vì vậy, nó thực sự thậm chí còn tồi tệ hơn những gì bạn ám chỉ trong câu cuối cùng của đoạn thứ hai.
CVn

@EuroMicelli đó là một thông tin rất thoải mái thực sự nhờ cho :) rằng
JAVA

27

Vâng, nó có thể .

Ví dụ, trong phương ngữ của C được sử dụng trong hệ điều hành Plan 9main thường được khai báo là một voidhàm, nhưng trạng thái thoát được trả về môi trường gọi bằng cách chuyển một con trỏ chuỗi đến exits()hàm. Chuỗi rỗng biểu thị thành công và bất kỳ chuỗi không trống nào biểu thị một số loại thất bại. Điều này có thể đã được thực hiện bằng cách maintrả lại một char*kết quả.

Và chắc chắn sẽ có thể thực hiện một hệ thống có trạng thái thoát floathoặc doublethoát.

Vậy tại sao int? Nó chỉ là một vấn đề của hội nghị - và có một to lớn giá trị trong việc có hệ điều hành và các chương trình mà chạy theo họ tuân theo một quy ước chung.

Quy ước Unix là sử dụng mã trạng thái số nguyên, với 0 biểu thị thành công và thất bại biểu thị khác không (vì thông thường chỉ có một cách để thành công, nhưng nhiều cách để thất bại). Tôi không biết liệu quy ước đó có bắt nguồn từ Unix hay không; Tôi nghi ngờ nó đến từ các hệ điều hành trước đó.

Dấu phẩy động sẽ là một quy ước khó khăn hơn, bởi vì (a) hỗ trợ điểm nổi không phổ biến, (b) khó xác định ánh xạ giữa các giá trị dấu phẩy động và điều kiện lỗi, (c) các hệ thống khác nhau sử dụng các dấu phẩy động khác nhau biểu diễn điểm và (d) chỉ cần tưởng tượng niềm vui của việc theo dõi lỗi làm tròn trong trạng thái thoát chương trình của bạn. Mặt khác, các số nguyên cho vay rất tốt để liệt kê các mã lỗi.

Như tôi đã đề cập, Kế hoạch 9 sử dụng các chuỗi, nhưng điều đó đặt ra một số phức tạp cho việc quản lý bộ nhớ, mã hóa ký tự, v.v. Theo như tôi biết, đó là một ý tưởng mới khi Kế hoạch 9 thực hiện và nó không thay thế được hiện tại quy ước rộng rãi.

(Ngẫu nhiên, trong C ++ chỉmain có thể quay lại và trong C chỉ được phép nếu trình biên dịch hỗ trợ cụ thể. Nhiều trình biên dịch không phàn nàn rất lớn nếu bạn viết , nhưng chỉ hơi cường điệu khi nói rằng nó sai .)intvoid mainvoid main


9

Giá trị được trả về bởi phương thức chính là "mã thoát". Nó được sử dụng bởi ứng dụng người gọi (thường là bash) để kiểm tra xem chương trình có kết thúc như mong đợi hay không. Trả về một số nguyên là cách dễ nhất để làm điều đó ở cấp độ HĐH. Double không có ý nghĩa gì đối với mã lỗi và Chuỗi khó duy trì ở cấp độ HĐH (không có GC).


3
Tại sao một chuỗi cần phải được thu thập rác trong khi số nguyên thì không?
Brad

4
@Brad, các chuỗi có độ dài thay đổi đối với chúng và về bản chất sẽ giống như trả lại một mảng có thể là một ký tự hoặc nó có thể là hàng ngàn. Bộ nhớ động sẽ là một nỗi đau trong khi int là một kích thước khá cố định mà không quá khó để xử lý.
JB King
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.