Sự khác biệt giữa hàm () và hàm (void) là gì?


27

Tôi đã nghe nói rằng đó là một cách thực hành tốt để viết các hàm không nhận được bất cứ thứ gì như một tham số như thế này:

int func(void);

Nhưng tôi nghe rằng cách đúng để diễn đạt như thế này:

int func();

Sự khác biệt giữa hai khai báo hàm này trong cả C và C ++ là gì?


5
Đây là một bản sao của hàng ngàn câu hỏi khác trên mạng của trang web, trong số những câu hỏi khác stackoverflow.com/questions/18167390/
Kẻ

@LarsViklund nó chỉ là một bản sao nếu có một câu hỏi trên trang web này. Tôi không thể tìm thấy một cái, vì vậy bất kể những gì trên SO, đây không phải là một bản sao. Có lẽ đáng để giữ câu hỏi này như một biển chỉ dẫn nếu không có gì khác.


1
@LightnessRacesinOrbit chúng tôi đã thảo luận trong trò chuyện và quyết định giữ nó xung quanh với một số chỉnh sửa.

Câu trả lời:


17

C và C ++ là khác nhau về mặt này.

Tiêu chuẩn trực tuyến C 2011

6.7.6.3 Các bộ khai báo hàm (bao gồm các nguyên mẫu)
...
10 Trường hợp đặc biệt của một tham số không tên thuộc loại voidlà mục duy nhất trong danh sách chỉ định rằng hàm không có tham số.
...
14 Một danh sách định danh chỉ khai báo các định danh của các tham số của hàm. Một danh sách trống trong một bộ khai báo hàm là một phần của định nghĩa của hàm đó xác định rằng hàm không có tham số. Danh sách trống trong bộ khai báo hàm không phải là một phần của định nghĩa của hàm đó xác định rằng không có thông tin nào về số lượng hoặc loại tham số được cung cấp. 145)

Nói tóm lại, một danh sách tham số trống trong khai báo hàm chỉ ra rằng hàm lấy số lượng tham số không xác định , trong khi danh sách tham số trống trong định nghĩa hàm chỉ ra rằng hàm không có tham số.

T foo( void ); // declaration, foo takes no parameters
T bar();       // declaration, bar takes an *unspecified* number of parameters

T foo( void ) { ... } // definition, foo takes no parameters
T bar() { ... }       // definition, bar takes no parameters

Theo như C có liên quan, bạn không bao giờ nên sử dụng danh sách định danh trống trong khai báo hoặc định nghĩa hàm. Nếu một hàm không có nghĩa là lấy bất kỳ tham số nào, hãy xác định rằng bằng cách sử dụng voidtrong danh sách tham số.

Tiêu chuẩn C ++ trực tuyến

8.3.5 Hàm [dcl.fct]
...
4 Mệnh đề khai báo tham số xác định các đối số có thể được chỉ định và xử lý của chúng, khi hàm được gọi. [ Lưu ý: các tham số-khai-khoản được sử dụng để chuyển đổi các đối số quy định về các cuộc gọi chức năng; xem 5.2.2. - lưu ý cuối ] Nếu mệnh đề khai báo tham số trống, hàm không có đối số. Một danh sách tham số bao gồm một tham số chưa đặt tên thuộc loại không phụ thuộc voidtương đương với danh sách tham số trống. Ngoại trừ trường hợp đặc biệt này, một tham số sẽ không có loại cv void. Nếu mệnh đề-khai báo-mệnh đềchấm dứt bằng dấu chấm lửng hoặc gói tham số chức năng (14,5.3), số lượng đối số sẽ bằng hoặc lớn hơn số lượng tham số không có đối số mặc định và không phải là gói tham số chức năng. Trường hợp chính xác về mặt cú pháp và nơi mà ... ... không phải là một phần của công cụ khai báo trừu tượng , thì, ... [ Ví dụ: tờ khai
    int printf(const char*, ...);
khai báo một hàm có thể được gọi với các số lượng và loại đối số khác nhau.
    printf("hello world");
    printf("a=%d b=%d", a, b);
Tuy nhiên, đối số đầu tiên phải có một loại có thể được chuyển đổi sang một const char*- cuối dụ ] [ Chú ý: Các tiêu đề chuẩn <cstdarg>bao gồm một cơ chế cho các đối số truy cập được thông qua bằng cách sử dụng lược (xem 5.2.2 và 18.10). - lưu ý cuối ]

Trong trường hợp của C ++, một danh sách tham số trống trong khai báo hoặc định nghĩa chỉ ra rằng hàm không có đối số và tương đương với việc sử dụng danh sách tham số void.


35

Trong C, một hàm với danh sách tham số trống ()có thể lấy bất cứ thứ gì cho các đối số của nó. Nghĩa đen bất cứ điều gì. Điều này thường được sử dụng để thực hiện một hàm có thể có số lượng đối số thay đổi , mặc dù ngày nay, nó được coi là thích hợp hơn để sử dụng cú pháp dấu chấm lửng rõ ràng hơn (...)cho các hàm này.

Trong C, một hàm với danh sách tham số (void)rõ ràng không có gì cho các đối số của nó. Điều đó có nghĩa là trình biên dịch thực sự có thể cho bạn biết bạn đã mắc lỗi nếu bạn cố gắng vượt qua điều gì đó.

Trong C ++, các khai báo hàm này là tương đương. Một danh sách tham số trống có nghĩa là "không có tham số" giống như void.


Re: "Điều này thường được sử dụng để thực hiện một hàm có thể có số lượng đối số thay đổi": Bạn có chắc chắn về điều này? Tôi không nghĩ rằng tôi đã từng thấy một chương trình sử dụng danh sách tham số rõ ràng để khai báo về các hàm không biến đổi và ()cho các hàm của hàm biến đổi . Bạn có một ví dụ về một chương trình sử dụng quy ước này?
ruakh

4
Hàm AC matrixdic phải được xác định theo ...cú pháp và nó phải có ít nhất một tham số được đặt tên. Xác định hàm như vậy với các ()nguyên nhân gây ra hành vi không xác định - và không có cách nào để phần thân của hàm sử dụng các macro được xác định <stdarg.h>để đọc các giá trị tham số. Đây là trường hợp kể từ tiêu chuẩn 1989/1990.
Keith Thompson

@KeithThndry: Câu hỏi này và câu trả lời này đang nói về các tiền đề, không phải định nghĩa hàm.
ruakh

3
@ruakh: Một hàm matrixdic phải được khai báo định nghĩa bằng ...cú pháp để tránh hành vi không xác định.
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.