foo(void)与foo(void *)的区别

9

就功能和语法而言,函数原型为int foo(void)int foo(void *)之间有区别吗?

我知道int bar(int)int bar(int *)之间的区别 - 其中一个正在寻找整数,而另一个正在寻找整数指针。 void是否也是如此?


相关问题的答案:https://dev59.com/sHNA5IYBdhLWcg3wPLL-#1043209。 - R Sahu
可能更有趣的是 foo(void)foo() 之间的区别。 - Maxim Egorushkin
3个回答

11
这个关于软件工程的回答中,void根据使用方式有特殊处理。在CC++中,void用于表示缺少数据类型,void *用于表示指向内存中某些没有类型的数据/空间的指针。void *不能直接进行解引用,必须先转换为另一种类型。在C中,此转换不需要显式说明,但在C++中必须显式说明。(这就是为什么我们不需要对malloc的返回值进行转换,它是void *类型的原因。)
当将void作为参数使用时,它表示完全没有任何参数,并且这是唯一允许的参数。试图像变量类型一样使用void或包含其他参数会导致编译器错误:
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);
             ^

同样不可能使用类型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;

void作为函数的返回值表示不会返回任何数据。由于无法声明类型为void的变量,因此即使使用void指针也无法捕获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);
    ^ ~~~~~~

类型不明确的 void * 是一个特殊情况。指向内存位置的指针称为 void 指针,但是它不指示该指针处数据的类型。(这种方法用于在 C 中实现多态性,例如 qsort() 函数。)然而,这些指针使用起来可能会很棘手,因为很容易意外将它们转换为错误的类型。下面的代码在 C 中不会抛出任何编译器错误,但会导致未定义的行为:
#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);
}

以下代码是完全合法的; 将void指针进行强制类型转换并不会改变它所持有的值。
#include <stdio.h>

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

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

47.200000

作为函数参数,void * 表示传入指针的数据类型未知,需要程序员适当处理该内存位置上的任何内容。作为返回值,void * 表示返回的数据类型未知或无类型,必须由程序处理。
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 表示“无数据”,表示没有返回值或参数,函数原型中的 void * 表示“指针所指向的数据类型未知”,表示必须将指针强制转换为不同类型,才能使用指针所指向的数据作为参数或返回值。


void * ... must be cast to another type first, but may be done so without an explicit cast. 这在 C++ 中并不正确。在 C++ 中,void* 的转换必须是显式的。另外,称呼一个转换为显式转换是多余的,因为按照定义,转换本身就是显式的。 - eerorika
已更新以反映C/C++的差异,感谢您让我知道! - Nick Reed

5

foo(void) - 没有参数的函数

foo(void *) - 带有一个 void * 参数的函数

void * 是什么?它只是指向没有指定类型的数据的指针。它可以被转换为任何其他指针类型。

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

这是一个非常重要的答案,因此它是最好的答案。我只想强调一下,在(type) vs. (type *)的世界中,这是一个例外,因为void实际上不是一种类型。 - Roberto Caboni

2
功能和语法上讲,函数原型为 int foo(void) 和 int foo(void *) 有区别吗?
这两者是不同的:
int foo(void) 声明了一个不接受任何参数的函数。
int foo(void *) 声明了一个接受一个 void* 类型参数的函数。
在 C++ 中,int foo(void) 相当于 int foo()。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接