没有参数的函数 - void和void*有什么区别?

5

我知道你可以只是这样简单地声明一个没有任何参数的函数:

void test()
{
    cout << "Hello world!!" << endl;
}

但我也见过

void test(void)
{
    cout << "Hello world!!" << endl;
}

并且

void test(void*)
{
    cout << "Hello world!!" << endl;
}

我的问题是:在这里使用voidvoid*有什么区别?


2
在C++中,test()test(void)是等效的,但在C语言中不是。除非需要C兼容性,否则应该优先选择前一种形式。函数test(void*)与其他两个函数不同;它带有一个未命名的void*类型参数。 - Brian61354270
void 表示“什么也没有”,而 void* 表示“某个东西的位置”。什么都没有和一个位置之间有很大的区别。 - molbdnilo
1
还有这个问答:https://dev59.com/ZLfna4cB1Zd3GeqPs3Jd - StoryTeller - Unslander Monica
3
“void*”本质上是一种无类型的指针,它指向原始内存地址。它可以指向任何“对象”,你可以将它设置为“null”以使它不指向任何东西。 - Robert Harvey
1
@super 像 C 和 C++ 中的许多其他事物一样,“void”这个词根据上下文的不同含义也不同。单独使用时表示“无”,加上星号则表示“任何东西”。(当你接触到“static”和“operator”时,会有很多有趣的事情发生。) - molbdnilo
显示剩余4条评论
4个回答

7
在C++中,没有参数的函数唯一的形式应该是:
void test();

表单:
void test(void)

这就是在中定义无参数函数的方式。但在C++中,仅仅用于与进行接口编程:
extern "C"
{
void test(void);
}

这个表单:

void test(void*)

这不是一个没有参数的函数。它有一个未命名的void*类型的参数。当调用时,它期望一个void*指针。

关于void*指针的解释,请查看这里:什么是void*指针及其使用方法?


6
在这里使用voidvoid*有什么区别?
当参数的类型为void时,必须在不带任何参数的情况下调用函数。
当参数的类型为void*时,必须使用一个void*类型的参数来调用函数,或者可以转换为void*类型的参数。 void代表"无",但void*并不代表"指向无"。事实上,它恰恰相反。void*表示指向任何东西,除了void。虽然这是个矛盾的说法,但这就是语言定义这两个类型的方式。

为什么会这样? - user2039981
test(void) 是为了 C 兼容性而存在的。C 需要它来向后兼容早期版本的 C,因为这些版本在参数列表中没有参数类型。 - Barmar
关于空指针:https://dev59.com/uWoy5IYBdhLWcg3wdt4L - drescherjm
“oxymoronic” - 让我开心了一整天。 - user2039981

3
我的问题是:在这里使用void和void*的区别是什么?
(void)参数列表与空参数列表相同。在C++中,void在这里并不起作用,除非需要与C兼容 - 参见答案的第二部分。
(void*)不接受0个参数。它接受1个参数。参数的类型是void*,它是一个指针类型。
为什么会这样?
这是由于向后兼容C。在C中,(void)是声明只接受空参数列表的函数的唯一方式。()参数列表声明任何未指定参数的函数。参数数量可以是任意的,包括0。在C中使用()参数列表已成为一种过时的特性。
引用自C11标准草案N1548:
函数声明符(包括原型) 标识符列表仅声明函数参数的标识符。函数声明符中的空列表指定该函数没有参数。函数声明符中的空列表,它不是该函数定义的一部分,则指定不提供有关参数数量或类型的信息。
未来语言方向 函数声明符 使用带有空括号的函数声明符(而非原型格式的参数类型声明符)是一种过时的特性。 函数定义 使用具有单独的参数标识符和声明列表(而非原型格式的参数类型和标识符声明符)的函数定义是一种过时的特性。
C之所以如此,是因为要向后兼容旧版本(标准之前)的C,其中未声明参数列表。

"() 参数列表声明了一个接受任意数量参数的函数。" 你能详细说明一下 "()" 吗? - Roko C. Buljan
@RokoC.Buljan 这是 K&R C 的遗留问题,当时你没有在参数列表中声明函数的参数。 - Barmar
@RokoC.Buljan 我添加了语言规则以进一步解释它。 - eerorika

3
在C++中,这两个函数声明:
void test();

void test(void);

这两个声明等价,意味着该函数不接受任何参数。

在C语言中,第一个函数声明声明了一个没有标识符的空标识符列表函数,而第二个函数声明声明了一个具有参数类型列表的函数,实际上没有参数。

根据C标准(6.9.1 函数定义):

5 如果声明符包括参数类型列表,则每个参数的声明都必须包括标识符, 唯一的特殊情况是只有一个类型为 void 的参数列表,在这种情况下,不应有标识符。不得跟随任何声明列表。

此函数声明也是其定义。

void test(void*)
{
    //...
}

该函数有1个参数,是一个void *类型的对象(请注意,指针始终是完整类型),在该函数中未被使用。

这个声明在C++中是有效的,在C中是无效的。因为在C中,函数声明中的每个函数参数都必须有一个标识符,除非使用了void参数,正如上述引用所指定的那样。

在C中只有在声明与定义不同时才可以使用这样的声明方式。

例如,在C中你可以这样写:

void test(void*); // declaratipon

然后

void test( void *ptr ) // declaration and definition
{
    //...
}

有一个参数,类型为void *的对象。 - nicomp
1
@nicomp 指针是对象。例如,在C语言中,对象被定义为“数据存储区域在执行环境中的一部分,其内容可以表示值”。 - Vlad from Moscow

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