Tại sao trả về NULL từ main ()?


10

Đôi khi tôi thấy các lập trình viên sử dụng NULLlàm giá trị trả về của main()các chương trình C và C ++, ví dụ như một cái gì đó như thế:

#include <stdio.h>

int main()
{
    printf("HelloWorld!");

    return NULL;
} 

Khi tôi biên dịch mã `này với gcc, tôi nhận được cảnh báo:

cảnh báo: return tạo số nguyên từ con trỏ mà không cần cast [-Wint-convert]

Điều này là hợp lý bởi vì macro NULLsẽ được mở rộng (void*) 0và giá trị trả về của chính sẽ là loại int.

Khi tôi thực hiện một chương trình C ++ ngắn gồm:

#include <iostream>
using namespace std;

int main()
{
    cout << "HelloWorld!";

    return NULL;
}

Và biên dịch nó với g ++, tôi nhận được một cảnh báo tương đương:

cảnh báo: chuyển đổi sang loại không phải con trỏ 'int' từ NULL [-Wconversion-null]

Nhưng tại sao họ sử dụng NULLlàm giá trị trả về main()khi nó đưa ra cảnh báo? Có phải chỉ là phong cách mã hóa xấu?


  • Lý do để sử dụng NULLthay vì 0giá trị trả lại của main()bất chấp cảnh báo là gì?
  • Được xác định theo triển khai nếu điều này phù hợp hay không và nếu vậy tại sao mọi thực hiện sẽ muốn lấy lại giá trị con trỏ?

4
Bạn nên hỏi họ trực tiếp.
juanchopanza

5
"tại sao họ sử dụng NULL làm giá trị trả về của hàm main ()" - chúng tôi không. Tác giả của mã đó. Tôi muốn nghe về nỗ lực của họ để giải thích lý do tại sao.
WhozCraig

1
@Vlad từ Moscow có nhưng tôi phải kiểm tra xem nó có thực sự là 0. ^^ - EXIT_FAILURElà 8 và có vẻ như sử dụng 1 không tốt cho một thất bại vì đôi khi nó được sử dụng như một thành công trong một số chương trình.
Waelmio

2
@RobertSsupportsMonicaCellio nếu đó thực sự là phản hồi bạn nhận được, điều đó thật đáng buồn. Đầu tiên, nó không có ý nghĩa (sẽ có ý nghĩa hơn nếu nó ở khắp mọi nơi chứ không phải bất cứ nơi nào ). Thứ hai, nó là một bán hết. Nếu bạn đang viết mã, tốt hơn là bạn nên có một la bàn tốt về việc liệu nó có đúng không; không chỉ đi với nó bởi vì đó là cách nó dường như được thực hiện bởi ... một ai đó. Bạn dường như có cây kim đó chỉ đúng hướng (vì vậy tại sao bạn hỏi); không quá nhiều người đã viết mã đó, sau đó cho bạn câu trả lời đó là lý do tại sao.
WhozCraig

2
Trong c, việc xác định NULLcon trỏ là 0(không có cast void *) là hoàn toàn hợp lệ . Trong trường hợp này, lỗ hổng không được chú ý và không tạo ra cảnh báo. Nó vẫn không phải là những gì NULL nên được sử dụng cho.
Ctx

Câu trả lời:


14

cái nào hợp lý

Đúng.

bởi vì macro NULLsẽ được mở rộng thành(void*) 0

Không. Trong C ++, macro NULL không được mở rộng thành (void*) 0[support.types.nullptr]. Nó chỉ có thể làm như vậy trong C.

Dù bằng cách nào, việc viết mã như thế này là sai lệch vì NULLđược cho là liên quan đến hằng số con trỏ null , bất kể nó được triển khai như thế nào. Sử dụng nó thay cho một intlỗi là một logic.

  • Lý do để sử dụng NULLthay vì 0 là giá trị trả về main()mặc dù có cảnh báo là gì?

Vô minh. Không có tốt lý do để làm điều này.

  • Được xác định theo triển khai nếu điều này phù hợp hay không và nếu vậy tại sao mọi thực hiện sẽ muốn lấy lại giá trị con trỏ?

Không, nó không bao giờ thích hợp . Nó tùy thuộc vào việc thực hiện cho dù trình biên dịch cho phép nó. Một trình biên dịch C ++ phù hợp cũng có thể cho phép nó mà không cần cảnh báo.


1
Thump thông thường của tôi: nó không được xác định bởi trình biên dịch cho dù trình biên dịch cho phép nó; nó là cụ thể cụ thể . Trong tiêu chuẩn, "định nghĩa cấy ghép" có nghĩa là việc triển khai phải ghi lại những gì nó làm.
Pete Becker

@PeteBecker Tôi đã tạm dừng khi viết nó nhưng dù sao đi nữa (vì cách thực hiện và các cụm từ tương tự của Wikipedia chỉ nghe có vẻ không tự nhiên). Nhưng bạn đã đúng, tôi sẽ thay đổi nó.
Konrad Rudolph

Dường như với tôi rằng lý do duy nhất "định nghĩa thực hiện" nghe có vẻ tự nhiên là mọi người đã quen nhìn thấy nó bị lạm dụng. <g>
Pete Becker

8

Khi tôi biên dịch mã `này với gcc, tôi nhận được cảnh báo:

warning: return makes integer from pointer without a cast

Điều này là do bạn biên dịch với các tùy chọn trình biên dịch lỏng lẻo. Sử dụng các cài đặt tiêu chuẩn C nghiêm ngặt -std=c11 -pedantic-errorsvà bạn sẽ nhận được lỗi trình biên dịch dự kiến, trên các cài đặt trong đó NULLmở rộng thành hằng số con trỏ null (void*)0. Xem Con trỏ của Viking từ số nguyên / số nguyên từ con trỏ mà không có sự cố cast .

Trên các triển khai nơi NULLmở rộng tới 0, mã nói đúng theo tiêu chuẩn, nhưng kiểu rất xấu, không di động và tệ nhất trong tất cả: hoàn toàn vô nghĩa.

Và biên dịch nó với g ++, tôi nhận được một cảnh báo tương đương:

warning: converting to non-pointer type int from NULL [-Wconversion-null]

Trên C ++ 11 trở lên, NULLkhông nên sử dụng - thay vào đó hãy sử dụng nullptr. Để trả về nó từ hàm main () là không chính xác. NULLluôn mở rộng sang 0C ++ nên nói đúng ra nó sẽ hoạt động, nhưng nó là phong cách rất tệ và tệ nhất trong tất cả: hoàn toàn vô nghĩa.

Có phải chỉ là phong cách mã hóa xấu?

Không chỉ xấu, mà phong cách mã hóa vô nghĩa mà không có bất kỳ lý do. Các lập trình viên đã viết nó là bất tài.


2

Có phải chỉ là phong cách mã hóa xấu?

Tệ hơn Cách chính xác để chỉ ra rằng chương trình đã hoàn thành tốt là

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}

1
Đó là nghề giáo thuần túy. Theo tiêu chuẩn C, một đối số 0 đến exit()(hoặc giá trị trả về 0 từ chính) có nghĩa giống như EXIT_SUCCESS.
mosvy

Và vì c99 bạn chỉ có thể bỏ qua returntừ main. Vì vậy, một phiên bản "chính xác" hơn của chương trình của bạn là int main(void){};-)
mosvy

1

Trong? Một số / nhiều / tất cả? Triển khai C ++ NULLlà một macro được mở rộng thành 0.

Điều này khi mở rộng có hiệu lực cho return 0. Đó là một giá trị trả lại hợp lệ.

Có phải chỉ là phong cách mã hóa xấu?

Đúng.

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.