调用参数为void*的函数时,是否需显式转换以符合C标准?
调用
void foo(void*)时是否需要显式转换参数? 先看函数声明:
void foo(void *);
我们结合C标准的条款来分析:
函数调用的参数转换规则(6.5.2.2/p7)
若表示被调用函数的表达式包含原型,则参数会被隐式转换,如同通过赋值操作转换为对应参数的类型,将每个参数的类型视为其声明类型的非限定版本。
也就是说,调用带原型的函数时,实参会按照简单赋值规则隐式转换为形参的类型。
简单赋值的指针转换规则(6.5.16.1/p1)
左操作数具有原子、限定或非限定指针类型,且(考虑左操作数经左值转换后的类型)一个操作数是指向对象类型的指针,另一个是指向限定或非限定void的指针,且左操作数指向的类型具备右操作数指向类型的所有限定符;
这里的关键是:当右操作数是对象类型指针,左操作数是void*时,完全满足该规则——void*没有额外限定符,自然被对象指针的限定符(如果有的话)包含。这意味着对象指针可以隐式赋值给void*,反过来(void*转对象指针)需要确保类型匹配,但这里属于前者场景。
指针转换的补充规定(6.3.2.3/p1)
void指针可与任意对象类型的指针相互转换。
这条规则直接明确了void*和对象指针的双向转换合法性,其中对象指针转void*的隐式转换完全被标准允许。
示例代码分析
对于这段代码:
struct some_struct *ptr = /* ... */; foo(ptr); // 直接传递对象指针 foo((void *) ptr); // 显式转换后传递
foo(ptr)完全符合C标准,不需要显式转换。编译器会根据函数原型自动将struct some_struct*隐式转换为void*,这一过程完全符合上述所有标准条款的要求。
原文认为必须显式转换是错误的,C标准从未要求这种场景下必须手动转换。
内容的提问来源于stack exchange,提问作者St.Antario
相关产品推荐
相关产品推荐

