考虑以下函数声明:
void foo(void *);
标准有关于函数调用的明确段落
6.5.2.2/p7
:
如果表示被调用函数的表达式的类型为 确实包含原型,参数被隐式转换,如 如果通过赋值,则给对应参数的类型,取 每个参数的类型是其非限定版本 声明类型。
因此,参数转换就像通过简单赋值一样执行。现在考虑简单赋值的规则
6.5.16.1/p1
:
左操作数具有原子、限定或非限定指针类型, 和(考虑左操作数在左值之后的类型 转换)一个操作数是指向对象类型的指针,另一个操作数是 是指向 void 的限定或非限定版本的指针,并且 左边指向的类型具有所指向类型的所有限定符 到右边;
因此,从
void *
到任何指针类型的转换(但反之亦然)是由赋值运算符的规则保证的。现在,由于 6.3.2.3/p1
保证了转换为 void *
的合法性:
指向 void 的指针可以与指向任何对象的指针相互转换 类型。
为了调用函数,需要显式
(void *)
。示例:
struct some_struct *ptr = //...
foo(ptr) // non conforming
foo((void *) ptr) //conforming
问题: 在调用上面示例中的函数时是否需要显式转换为
void *
才能保持一致性,还是我错过了某些内容?
你错过了一些东西 - 即使你引用了它。
考虑问题中代码的稍微修改版本:
void foo(void *p);
struct some_struct *ptr;
foo(ptr);
当我们调用
foo
时,我们将其参数 p
赋值为
void *p = ptr;
这是完全有效的,因为
ptr
)是指向对象类型的指针,另一个(p
)是指向void
的限定或非限定版本的指针,并且