首页 > 解决方案 > 为什么我可以将多个指针传递给单个指针参数?

问题描述

我刚刚发现我可以将双指针传递给需要单指针作为参数的函数。

void func(void *p) {}

void **p;
func(p);

我什至可以这样做:

void memcpy(void *dst, void *src) {}

void ****dst, *********src;
memcpy(dst, src);

似乎发生了隐式转换。

但是,这种转换的规则是什么?标准怎么说?

标签: cpointers

解决方案


当一个函数被调用时,那么(6.5.2.2):

...参数被隐式转换为相应参数的类型,就像通过赋值一样

因此,为了查看是否允许我们将某些内容传递给函数,我们需要检查分配规则。在简单赋值的规则中,列出了所有有效的形式,包括这个(6.5.16.1,强调我的):

  • 左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后将具有的类型)一个操作数是指向对象类型的指针,另一个是指向限定或非限定版本的指针void, left 指向的类型具有 right 指向的类型的所有限定符;

这意味着我们可以隐式地将对象指针类型分配给 a void*,反之亦然。当我们将参数传递给函数时也是如此。

这就是为什么您没有收到诊断消息的原因,void*这是一种特殊情况,它是一种通用对象指针类型,可以与任何其他对象指针类型一起使用。请注意,我使用术语对象指针,因为您不能void*与函数指针混合使用。

6.3.2.3 规定了如何进行实际转换:

指向的指针void可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转​​换。指向任何对象类型的指针都可以转换为指向void和返回的指针;结果应与原始指针比较。

这些特殊规则仅适用于void*. 它们不会“递归地”应用于void**. 但是 avoid**仍然是对象指针类型,因此您可以将它分配给 a void*etc 。但是你不能从 例如double**void**

但是请注意,必须遵守上述 6.5.16.1 中所写的限定符 ( const, )。volatile我们可以将非限定类型分配给限定类型,但不能反过来。(另见 6.3.2.3/2)


推荐阅读