c - 为什么我可以将多个指针传递给单个指针参数?
问题描述
我刚刚发现我可以将双指针传递给需要单指针作为参数的函数。
void func(void *p) {}
void **p;
func(p);
我什至可以这样做:
void memcpy(void *dst, void *src) {}
void ****dst, *********src;
memcpy(dst, src);
似乎发生了隐式转换。
但是,这种转换的规则是什么?标准怎么说?
解决方案
当一个函数被调用时,那么(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)
推荐阅读
- select - Infoset 查询 SELECT SUM 问题
- c# - 从 C# 在 docker 容器内通过 SSH 运行多个命令
- android - 如何从onActivityResult中获取位图信息并在同一个Activity中使用
- haskell - “最后一条消息的输入太短”与 netlink 库
- python - Django模板标签:获取字典的键、值
- fortran - 将 2 行 3 列的矩阵数组写入 Fortran 95 中的输出文本文件
- laravel - 如何在 laravel 控制器中处理 json 请求?
- c# - c# http请求最大并发连接数为40
- ssl - ssl证书解决方案
- javascript - MIME 类型(“text/html”)不是有效的 JavaScript MIME 类型