参数转换:(正常)指向void指针的指针,需要强制转换吗?

当分配到void -pointer或从void -pointer分配时,不需要强制转换(C99§6.3.2.2sub 1/§6.5.16.1sub 1)。 将(例如int – )指针传递给需要void -pointer的函数时,这也是正确的吗?

例如:

 void foo(void * p){ // Do something } int main(){ int i = 12; foo(&i); // int * to void *: no cast needed? } 

当我使用GCC(4.8.1,MinGW-32)编译它时,我既没有错误也没有警告(使用-Wall-pedantic )。

与此答案相反,建议此调用需要-Wformat (消除-Wformat警告):

 int main(){ int i = 12; printf("%p\n", &i); } 

但就我而言,海湾合作委员会并没有抱怨。

那么:将非void -pointer传递给需要void -pointer的函数时需要进行强制转换?

区别在于printf是一个可变参数函数,可变参数函数遵循其尾随参数的不同转换规则。

 foo(&i); 

这里不需要强制转换,因为foo是原型函数。 C表示&i被转换为p的类型,就像通过赋值一样,在C中,所有对象指针类型之间都隐含为void *

printf情况不同,因为像varf这样的可变参数函数对其余参数有默认参数提升,并且指针类型的参数不会发生转换。

关于原型函数的C:

(C99,6.5.2.2p7)“如果表示被调用函数的表达式具有包含原型的类型,则将参数隐式转换为相应参数的类型,就像通过赋值一样,取每个类型的类型参数是其声明类型的非限定版本。“

关于可变函数的C:

(C99,6.5.2.2p7)“(C99,6.5.2.2p7)”函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数之后停止。 默认参数提升是在尾随参数上执行的。“

那么:将非void指针传递给需要void指针的函数时需要强制转换吗?

对于printfp转换说明符需要void *参数。 如果参数的类型不同,则函数调用将调用未定义的行为。 因此,如果p的参数是对象指针类型,则需要(void *)强制转换。

(C99,7.19.6.1p8)“p参数应该是指向void的指针。”