foo (void) vs foo (void *)


9

Nói về mặt chức năng và cú pháp, có sự khác biệt giữa một chức năng mà nguyên mẫu của nó là int foo(void)int foo(void *)?

Tôi biết sự khác biệt giữa, ví dụ, int bar(int)int bar(int *)- một trong số họ đang tìm kiếm một int và người kia đang tìm kiếm một con trỏ int. Có voidhành xử giống như vậy?


Một câu trả lời cho một câu hỏi liên quan: stackoverflow.com/a/1043209/434551 .
R Sahu


Điều có thể thú vị hơn là sự khác biệt giữa foo(void)foo().
Maxim Egorushkin

Câu trả lời:


10

Từ câu trả lời này về Kỹ thuật phần mềm, void được xử lý đặc biệt tùy thuộc vào cách sử dụng. Trong CC++, voidđược sử dụng để biểu thị sự vắng mặt của một loại dữ liệu, trong khi đó void *được sử dụng để chỉ ra một con trỏ trỏ đến một số dữ liệu / không gian trong bộ nhớ không có loại. void *không thể tự hủy đăng ký và phải được chuyển sang loại khác trước. Diễn viên này không cần phải rõ ràng C, nhưng phải rõ ràng trong C++. (Đây là lý do tại sao chúng tôi không bỏ giá trị trả về của malloc void *.)


Khi được sử dụng với chức năng như một tham số, voidcó nghĩa là hoàn toàn không có bất kỳ tham số nào và là tham số duy nhất được phép. Cố gắng sử dụng void như một loại biến hoặc bao gồm các đối số khác dẫn đến lỗi trình biên dịch:

int foo(void, int);     //trying to use "void" as a parameter
int bar(void baz);      //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
       ^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
             ^

Tương tự không thể khai báo một biến có kiểu void:

int main(void) {
  void qux;         //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
  void qux;

voidnhư một giá trị trả về cho một hàm cho biết sẽ không có dữ liệu nào được trả về. Vì không thể khai báo một biến kiểu void, nên không thể bắt được giá trị trả về của voidhàm, ngay cả với một con trỏ void.

void foo(int i) { return; }

int main(void) {
  void *j;
  j = foo(0);

  return 0;
}
main.c:5:5: error: assigning to 'void *' from
      incompatible type 'void'
  j = foo(0);
    ^ ~~~~~~

Các typless void *là một trường hợp khác nhau. Một con trỏ void chỉ ra một con trỏ tới một vị trí trong bộ nhớ, nhưng không chỉ ra loại dữ liệu tại con trỏ đó. (Đây là cách được sử dụng để đạt được tính đa hình trong C , chẳng hạn như với hàm qsort () .) Những con trỏ này có thể khó sử dụng, tuy nhiên, rất dễ để vô tình chuyển chúng sang loại sai. Mã dưới đây sẽ không ném bất kỳ lỗi biên dịch nào C, nhưng dẫn đến hành vi không xác định:

#include <stdio.h>

int main(void) {
  double foo = 47.2;    //create a double
  void *bar = &foo;     //create a void pointer to that double
  char *baz = bar;      //create a char pointer from the void pointer, which
                        //is supposed to hold a double

  fprintf(stdout, "%s\n", baz);
}

Các mã sau đây, tuy nhiên, là hoàn toàn hợp pháp; truyền đến và từ một con trỏ trống không bao giờ thay đổi giá trị mà nó giữ.

#include <stdio.h>

int main(void) {
  double foo = 47.2;
  void *bar = &foo;
  double *baz = bar;

  fprintf(stdout, "%f\n", *baz);
}

47.200000

Là một tham số chức năng, void *chỉ ra rằng loại dữ liệu tại con trỏ bạn truyền vào không được biết, và người lập trình, tùy thuộc vào bạn để xử lý chính xác bất cứ thứ gì ở vị trí bộ nhớ đó. Là một giá trị trả về, void *chỉ ra rằng loại dữ liệu được trả về không được biết hoặc không có lỗi và phải được chương trình xử lý.

int quux(void *);   //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int);    //a function that receives an int, and returns a pointer to data whose type is not known.

tl; dr void trong một nguyên mẫu hàm có nghĩa là "không có dữ liệu" và cho biết không có giá trị trả về hoặc không có tham số, void *trong một nguyên mẫu hàm có nghĩa là "dữ liệu tại con trỏ mà hàm này được cung cấp không có kiểu đã biết" và chỉ ra một tham số hoặc giá trị trả về con trỏ của nó phải được chuyển sang một loại khác trước khi dữ liệu tại con trỏ có thể được sử dụng.


void * ... must be cast to another type first, but may be done so without an explicit cast.Không đúng trong C ++. Trong C ++, hình thức chuyển đổi void*phải rõ ràng. PS gọi một diễn viên rõ ràng là dư thừa vì định nghĩa là chuyển đổi rõ ràng.
eerorika

Cập nhật để phản ánh sự khác biệt của C / C ++, cảm ơn bạn đã cho tôi biết!
Nick Reed

4

foo(void) - hàm không có tham số

foo(void *)- hàm với một void *tham số

void *gì Nó chỉ là con trỏ tới dữ liệu không có kiểu xác định. Nó có thể được đúc cho bất kỳ loại con trỏ khác

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}

Câu trả lời cần thiết, vì vậy nó là một trong những tốt nhất. Tôi sẽ chỉ biết rằng đây là một ngoại lệ trong (type) vs. (type *)vũ trụ của các cặp vợ chồng vì khoảng trống không thực sự là một kiểu.
Roberto Caboni

2

Nói về mặt chức năng và cú pháp, có sự khác biệt giữa một hàm có nguyên mẫu là int foo (void) và int foo (void *) không?

Có một sự khác biệt:

int foo(void) tuyên bố một hàm chấp nhận không có đối số.

int foo(void *)khai báo một hàm chấp nhận kiểu đối số duy nhất void*.

Trong C ++, tương đương int foo(void)với int foo().

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.