Có sự khác biệt giữa foo (void) và foo () trong C ++ hoặc C không?


253

Hãy xem xét hai định nghĩa hàm:

void foo() { }

void foo(void) { }

Có sự khác biệt nào giữa hai điều này không? Nếu không, tại sao lại có voidtranh luận? Lý do thẩm mỹ?


Đối với C, Q / A ở đây
Antti Haapala

Câu trả lời:


317

Trong C :

  • void foo()có nghĩa là "một hàm foolấy một số lượng đối số không xác định thuộc loại không xác định"
  • void foo(void)có nghĩa là "một hàm fookhông có đối số"

Trong C ++ :

  • void foo()có nghĩa là "một hàm fookhông có đối số"
  • void foo(void)có nghĩa là "một hàm fookhông có đối số"

foo(void)Do đó, bằng cách viết , chúng tôi đạt được cùng một cách giải thích trên cả hai ngôn ngữ và làm cho các tiêu đề của chúng tôi trở nên đa ngôn ngữ (mặc dù chúng tôi thường cần phải làm thêm một số điều cho các tiêu đề để làm cho chúng thực sự là ngôn ngữ chéo; cụ thể là bọc chúng trong extern "C"khi chúng tôi biên dịch C ++).


10
Nhưng nếu C ++ đã yêu cầu void, thì nó có thể tránh được vấn đề "phân tích cú pháp nhất".
Adrian McCarthy

5
Đúng, nhưng có rất nhiều phân tích ngu ngốc khác trong C ++, không có điểm nào thực sự trong việc tìm hiểu về bất kỳ một trong số chúng.
DrPizza

16
Trong một câu hỏi gần đây, @James Kanze đã đăng một mẩu tin thú vị. Đăng lại ở đây để tránh mất nó: các phiên bản đầu tiên của C không cho phép chỉ định số lượng tham số mà hàm có thể thực hiện, do đó void foo()là cú pháp duy nhất để khai báo hàm. Khi chữ ký được giới thiệu, ủy ban C phải phân biệt tham số không có từ cú pháp cũ và đưa ra void foo(void)cú pháp. C ++ lấy nó vì mục đích tương thích.
Matthieu M.

3
Bạn có thể cho tôi một ví dụ về C C90 và sau đó sử dụng void foo()thay vì void foo(void)sẽ tạo ra sự khác biệt về chức năng không? Tức là tôi đã sử dụng phiên bản không có khoảng trống trong nhiều năm và chưa thấy vấn đề gì, tôi có thiếu điều gì không?
chacham15

6
@ chacham15 void foo() { if ( rand() ) foo(5); } biên dịch và chạy (gây ra hành vi không xác định trừ khi bạn rất may mắn), trong khi void foo(void)với cùng một cơ thể sẽ gây ra lỗi biên dịch.
MM

39

Tôi nhận ra câu hỏi của bạn liên quan đến C ++, nhưng khi nói đến C, câu trả lời có thể được tìm thấy trong K & R, trang 72-73:

Hơn nữa, nếu một khai báo hàm không bao gồm các đối số, như trong

double atof();

điều đó cũng được hiểu là không có gì được giả định về các đối số của atof; tất cả các kiểm tra tham số bị tắt. Ý nghĩa đặc biệt này của danh sách đối số trống nhằm cho phép các chương trình C cũ hơn biên dịch với trình biên dịch mới. Nhưng đó là một ý tưởng tồi để sử dụng nó với các chương trình mới. Nếu hàm lấy đối số, khai báo chúng; nếu nó không có đối số, sử dụng void.


Nhưng câu hỏi là về các định nghĩa, trong trường hợp đó, quy tắc C có liên quan là Danh sách trống trong 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ố.
jinawee

9

Dự thảo tiêu chuẩn C ++ 11 N3337

Không có sự khác biệt.

http://www.open-std.org/jtc1/sc22/wg21/docs/ con / 2012 / n3337.pdf

Phụ lục C "Tương thích" C.1.7 Khoản 8: người khai báo nói:

8.3.5 Thay đổi: Trong C ++, một hàm được khai báo với danh sách tham số trống không có đối số. Trong C, một danh sách tham số trống có nghĩa là số lượng và loại đối số của hàm không xác định.

Thí dụ:

int f();
// means int f(void) in C ++
// int f( unknown ) in C

Đặt vấn đề: Điều này là để tránh các lệnh gọi hàm sai (nghĩa là các hàm gọi sai số hoặc loại đối số).

Ảnh hưởng đến tính năng gốc: Thay đổi thành ngữ nghĩa của tính năng được xác định rõ. Tính năng này được đánh dấu là sự lỗi thời của người Viking trong C.

Các hàm 8.5.3 cho biết:

4. Mệnh đề khai báo tham số xác định các đối số có thể được chỉ định và xử lý chúng khi hàm được gọi. [...] Nếu mệnh đề khai báo tham số trống, hàm không có đối số. Danh sách tham số (void) tương đương với danh sách tham số trống.

C99

Như được đề cập bởi C ++ 11, int f()chỉ định không có gì về các đối số và là lỗi thời.

Nó có thể dẫn đến mã làm việc hoặc UB.

Tôi đã giải thích chi tiết về tiêu chuẩn C99 tại: https://stackoverflow.com/a/36292431/895245


2

Trong C, bạn sử dụng khoảng trống trong tham chiếu hàm trống để trình biên dịch có nguyên mẫu và nguyên mẫu đó "không có đối số". Trong C ++, bạn không cần phải nói với trình biên dịch rằng bạn có một nguyên mẫu vì bạn không thể bỏ qua nguyên mẫu.


1
"Nguyên mẫu" có nghĩa là kiểu khai báo và trả về danh sách đối số. Tôi nói điều này bởi vì "nguyên mẫu" lúc đầu làm tôi bối rối không hiểu ý bạn là gì.
Zan Lynx
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.