Tôi nên trả về EXIT_SUCCESS hoặc 0 từ hàm main ()?


124

Đó là một câu hỏi đơn giản, nhưng tôi cứ thấy những câu trả lời mâu thuẫn: liệu thói quen chính của chương trình C ++ có trở lại không 0 hay EXIT_SUCCESSkhông?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

hoặc là

int main(){return 0;}

Có phải chúng giống hệt nhau không? NênEXIT_SUCCESS chỉ được sử dụng với exit()?

Tôi nghĩ rằng EXIT_SUCCESSsẽ là một lựa chọn tốt hơn bởi vì phần mềm khác có thể muốn coi số 0 là thất bại, nhưng tôi cũng nghe nói rằng nếu bạn quay lại 0, trình biên dịch có khả năng thay đổi nó thành một giá trị khác.


Điều này có trả lời câu hỏi của bạn không? stackoverflow.com/questions/1188335/ Lời
Blastfurnace

2
Câu trả lời này về C90 diễn giải tiêu chuẩn - 0EXIT_SUCCESScả hai đều được hiểu là thành công.
ta.speot.is

Tôi sẽ trả lời ở đây vì tôi cảm thấy ai đó sẽ đọc nó trong tương lai. Về cơ bản có nhiều mô hình về "C chính xác" trông như thế nào. Một số mô hình thích sử dụng chữ trên macro, ví dụ, thay vì chuyển NULL làm đối số, chúng có thể chuyển (const char *) 0 để chỉ ra rằng nó không chỉ là null, nhưng nếu nó không phải là null, thì nó phải là một con trỏ ký tự không đổi. Các mô hình khác thích loại bất khả tri và bằng cách sử dụng các loại macro, họ có thể tránh phải thay đổi cơ sở mã khi mọi thứ thay đổi hoàn toàn. Ví dụ: nhiều người -
Dmitry

@Dmitry <contin> Các định nghĩa loại API của Windows không chính xác trong các nền tảng mới hơn, nhưng vì chúng là macro, nên chúng có cách dễ dàng thay đổi tất cả các loại thành các loại hoạt động bằng cách xác định lại macro và phần lớn các loại này được định nghĩa theo tỷ lệ (ví dụ: int là khác nhau trên các nền tảng khác nhau). Để tóm tắt, hãy sử dụng những thứ như EXIT_SUCCESS nếu mã trả về có vấn đề và có thể thay đổi trong tương lai, nếu không trả về 0 có vẻ như là một số ma thuật nhưng đó vẫn là quy ước tiêu chuẩn hoàn toàn hợp lệ. mã lỗi chủ yếu dành cho các chương trình dẫn đến kết quả số ống từ người này sang người khác, -
Dmitry

@Dmitry <tiếp tục> sử dụng mã lỗi để gỡ lỗi chương trình của bạn hơi yếu vì nếu nó trả về 0, thì đó là thông tin khá vô dụng trừ một số trường hợp khi có các lỗi chưa được xử lý trong chương trình có thể khiến chương trình bị hỏng một cách im lặng và bạn cần để kiểm tra xem nó có trở lại bình thường không (0) hoặc xảy ra lỗi im lặng. Việc trả về số hữu ích hơn cho đường ống 0..255 từ chương trình này sang chương trình khác dựa trên đầu vào của chúng, nếu không thì không có lý do gì để nghĩ về nó: hoặc trả về 0 hoặc sử dụng một chính được biên dịch trước để gọi một cuộc gọi "init" void không trực quan làm phiền bạn với sự trở lại vô ích
Dmitry

Câu trả lời:


150

EXIT_FAILURE, trong một câu lệnh return trong mainhoặc như là một đối số exit(), là cách di động duy nhất để chỉ ra lỗi trong chương trình C hoặc C ++. exit(1)thực sự có thể báo hiệu chấm dứt thành công trên VMS, ví dụ.

Nếu bạn sẽ sử dụng EXIT_FAILUREkhi chương trình của bạn thất bại, thì bạn cũng có thể sử dụng EXIT_SUCCESSkhi chương trình thành công, chỉ vì mục đích đối xứng.

Mặt khác, nếu chương trình không bao giờ báo hiệu sự cố, bạn có thể sử dụng 0hoặc EXIT_SUCCESS. Cả hai đều được đảm bảo bởi các tiêu chuẩn để báo hiệu hoàn thành thành công. (Hầu như không có khả năng nào EXIT_SUCCESScó thể có giá trị khác 0, nhưng nó bằng 0 trên mỗi lần thực hiện mà tôi từng nghe.)

Việc sử dụng 0có một lợi thế nhỏ mà bạn không cần #include <stdlib.h>trong C hoặc #include <cstdlib>trong C ++ (nếu bạn đang sử dụng một returncâu lệnh thay vì gọi điện exit()) - nhưng đối với một chương trình có kích thước đáng kể, bạn sẽ bao gồm trực tiếp hoặc gián tiếp dù sao.

Đối với vấn đề đó, trong C bắt đầu với tiêu chuẩn 1999 và trong tất cả các phiên bản của C ++, dù sao đi nữa, đến cuối cùng main()cũng có một ẩn ý return 0;, do đó bạn có thể không cần sử dụng 0hoặc EXIT_SUCCESSrõ ràng. (Nhưng ít nhất là trong C, tôi coi một phong cách rõ ràng return 0;là phong cách tốt hơn.)

(Có người hỏi về OpenVMS. Tôi đã không sử dụng nó trong một thời gian dài, nhưng khi tôi gọi lại giá trị trạng thái lẻ thành công thường biểu thị trong khi giá trị thậm chí biểu thị sự thất bại. Việc thực hiện C bản đồ 0để 1, do đó return 0;chỉ chấm dứt thành công. Các giá trị khác được truyền không thay đổi , do đó return 1;cũng chỉ ra việc chấm dứt thành công. EXIT_FAILUREsẽ có giá trị bằng không.)


@KeithThndry bạn có thể làm rõ câu trả lời của mình đối với VMS (OpenVMS?). Không rõ ràng mối quan hệ EXIT_SUCCESS / EXIT_FAILURE với 0 và 1. Tôi sẽ giải thích các giá trị lẻ / chẵn thay thế.
malat

@malat: Bạn có thực sự sử dụng VMS không?
Keith Thompson

không, không bao giờ sử dụng nó Tôi đã tìm kiếm một câu trả lời kinh điển, vì wikipedia đã sử dụng một từ ngữ khác .
malat

1
@Rhymoid: Điều này được chỉ định bởi C, không phải POSIX.
Keith Thompson

1
@DeanP: 0EXIT_SUCCESSkhông được đảm bảo có cùng giá trị (tôi đã đề cập rằng trong câu trả lời của tôi), nhưng cả hai đều biểu thị việc chấm dứt thành công. EXIT_SUCCESSlà tốt hơn về mặt phong cách nếu bạn cũng đang sử dụng EXIT_FAILURE, nhưng exit(0)vẫn ổn.
Keith Thompson

25

Không quan trọng. Cả hai đều giống nhau.

Báo giá tiêu chuẩn C ++:

Nếu giá trị của trạng thái bằng 0 hoặc EXIT_SUCCESS, một hình thức xác định thực hiện của chấm dứt thành công trạng thái được trả về.


12
Nó không quan trọng đối với trình biên dịch, nhưng nó có thể là vấn đề về phong cách.
celtschk

2
@celtschk: Vấn đề về phong cách dựa trên nhận thức hay còn gọi là Không chuẩn hóa nên không được tính là một sự khác biệt. Bạn chỉ có thể so sánh Táo với Táo không Táo với Lê.
Alok Lưu

3
Không có gì đảm bảo rằng EXIT_SUCCESS == 0. Mặt khác, không có lý do chính đáng nào để nó không tồn tại.
Keith Thompson

@KeithThndry: tại sao không có gì đảm bảo rằng EXIT_SUCCESS == 0.? Hãy giải thích rõ hơn.
Kẻ hủy diệt

2
@PravasiMeet: Một hệ thống có thể có nhiều hơn một giá trị biểu thị thành công.
Keith Thompson

11

0, theo định nghĩa, là một con số kỳ diệu. EXIT_SUCCESS gần như phổ biến bằng 0, đủ hạnh phúc. Vậy tại sao không chỉ trở về / thoát 0?

thoát (EXIT_SUCCESS); rất rõ ràng về ý nghĩa.

thoát (0); mặt khác, là phản trực giác trong một số cách. Ai đó không quen thuộc với hành vi shell có thể cho rằng 0 == false == xấu, giống như mọi cách sử dụng 0 khác trong C. Nhưng không - trong trường hợp đặc biệt này, 0 == thành công == tốt. Đối với hầu hết các nhà phát triển có kinh nghiệm, sẽ không là một vấn đề. Nhưng tại sao chuyến đi lên chàng trai mới hoàn toàn không có lý do?

tl; dr - nếu có một hằng số xác định cho số ma thuật của bạn, gần như không bao giờ có lý do để không sử dụng hằng số ở vị trí đầu tiên. Nó dễ tìm kiếm hơn, thường rõ ràng hơn, v.v. và nó không làm bạn mất gì.


Tôi nghĩ rằng ý kiến ​​của bạn về những người mong đợi 0 sẽ tự động xấu là không đúng. Rất nhiều API sử dụng 0 cho thành công và không 0 cho thất bại, ngay cả trong stdlib. Ví dụ stdlib ( fclose(), setvbuf(), ...), POSIX ( listen(), pthread_create(), pipe(), ...), và nhiều, nhiều thư viện khác (ví dụ như OpenGL [ glGetError()], zlib [ deflate()/ inflate()/ ...], SDL [ SDL_CreateWindowAndRenderer()/ ...], và hơn).
Tim as

2
Chắc chắn, có những trường hợp khác trong đó 0 được sử dụng cho 'thành công', nhưng anh ta nói đúng về việc nó gây nhầm lẫn.
Paul Wintz

10

Đây là một câu chuyện không bao giờ kết thúc phản ánh các giới hạn (một huyền thoại) về "khả năng tương tác và tính di động trên tất cả".

Những gì chương trình sẽ trả về để biểu thị "thành công" phải được xác định bởi người đang nhận giá trị (Hệ điều hành hoặc quá trình gọi chương trình) không phải bằng một đặc tả ngôn ngữ.

Nhưng các lập trình viên thích viết mã theo "cách di động" và do đó họ phát minh ra mô hình của riêng họ cho khái niệm "hệ điều hành" xác định các giá trị tượng trưng để trả về.

Bây giờ, trong một kịch bản nhiều-nhiều (trong đó nhiều ngôn ngữ phục vụ để viết chương trình cho nhiều hệ thống), sự tương ứng giữa quy ước ngôn ngữ cho "thành công" và hệ điều hành (mà không ai có thể luôn luôn giống nhau) nên được xử lý bằng cách triển khai cụ thể của một thư viện cho một nền tảng đích cụ thể.

Nhưng - thật không may - những khái niệm này không rõ ràng vào thời điểm ngôn ngữ C được triển khai (chủ yếu để viết kernel UNIX) và Gigagram của những cuốn sách được viết bằng cách nói "return 0 có nghĩa là thành công", vì điều đó đúng trên HĐH thời điểm đó có một trình biên dịch C.

Từ đó trở đi, không có tiêu chuẩn hóa rõ ràng nào được thực hiện về cách xử lý một sự tương ứng như vậy. C và C ++ có định nghĩa riêng về "giá trị trả về" nhưng không ai cấp một bản dịch hệ điều hành phù hợp (hoặc tốt hơn: không có tài liệu biên dịch nào nói gì về nó). 0 có nghĩa là thành công nếu đúng với UNIX - LINUX và - vì các lý do độc lập - đối với Windows, và điều này bao gồm 90% "máy tính tiêu dùng" hiện tại, trong hầu hết các trường hợp - bỏ qua giá trị trả về (vì vậy chúng ta có thể thảo luận trong nhiều thập kỷ, không ai sẽ nhận thấy!)

Trong kịch bản này, trước khi đưa ra quyết định, hãy hỏi những câu hỏi sau: - Tôi có muốn giao tiếp với người gọi về người hiện tại của tôi không? (Nếu tôi luôn luôn trả về 0 ... không có manh mối đằng sau tất cả mọi thứ) - Người gọi của tôi có những quy ước về giao tiếp này không? (Lưu ý rằng một giá trị không phải là quy ước: không cho phép bất kỳ biểu diễn thông tin nào)

Nếu cả hai câu trả lời này là không, có lẽ giải pháp tốt là không viết câu trả lời chính nào cả. (Và để trình biên dịch quyết định, liên quan đến mục tiêu đang hoạt động).

Nếu không có quy ước nào ở vị trí 0 = thành công đáp ứng hầu hết các tình huống (và sử dụng các biểu tượng có thể có vấn đề, nếu họ đưa ra một quy ước).

Nếu có các quy ước, đảm bảo sử dụng các hằng số tượng trưng gắn kết với chúng (và đảm bảo sự gắn kết quy ước, không phải là sự gắn kết giá trị, giữa các nền tảng).


4

Khi bạn bắt đầu viết mã có thể trả về vô số trạng thái thoát, bạn bắt đầu #define'nhập tất cả chúng. Trong trường hợp này EXIT_SUCCESScó ý nghĩa trong bối cảnh không phải là một " số ma thuật ". Điều này làm cho mã của bạn dễ đọc hơn bởi vì mọi mã thoát khác sẽ có EXIT_SOMETHING. Nếu bạn chỉ đơn giản viết một chương trình sẽ trả về khi nó hoàn thành, return 0là hợp lệ và thậm chí có thể sạch hơn bởi vì nó gợi ý rằng không có cấu trúc mã trả lại tinh vi.


0

Những gì bạn trở về từ một chương trình chỉ là một quy ước.

Không, tôi không thể nghĩ về bất kỳ trường hợp nào mà "EXIT_SUCCESS" sẽ không là "0".

Cá nhân, tôi khuyên bạn nên "0".

IMHO ...


1
Tôi đã lập trình C ++ được 10 năm và vẫn không thể nhớ nếu 0 có nghĩa là thành công hay thất bại về giá trị trả về.
lahjaton_j

@lahjaton_j Tôi hiểu. Nó nghĩ rằng đó là vì nó phản tác dụng trực quan: 0là sai và nhiều chức năng trả 0về thất bại / không làm gì cả.
ý nghĩa-vấn đề


-5

Một số trình biên dịch có thể tạo ra sự cố với điều này - trên trình biên dịch Mac C ++, EXIT_SUCCESS hoạt động tốt với tôi nhưng trên trình biên dịch Linux C ++, tôi phải thêm cstdlib để nó biết EXIT_SUCCESS là gì. Ngoài ra, họ là một và giống nhau.


Tôi có nghĩa là trên Mac EXIT_SUCCESS hoạt động mà không bao gồm cstdlib.
Ambidextrous

4
Nếu EXIT_SUCCESSlàm việc mà không bao gồm <stdlib.h>hoặc <cstdlib>, một số tiêu đề khác phải xác định nó, trực tiếp hoặc gián tiếp. Trong C ++, thông thường các tiêu đề tiêu chuẩn cho #includecác tiêu đề tiêu chuẩn khác. Nếu điều này biên dịch mà không có lỗi: int main() { return EXIT_SUCCESS; }thì trình biên dịch của bạn có thể có lỗi.
Keith Thompson
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.