你为什么要这样做:
void f(Struct** struct)
{
...
}
如果我想对结构列表进行操作,传递 a 还不够Struct*
吗?这样我可以struct++
解决下一个结构,还是我在这里很困惑?:)
如果我想以某种方式重新排列结构列表,它不是很有用吗?但是,如果我只是阅读,我不明白这一点。
你为什么要这样做:
void f(Struct** struct)
{
...
}
如果我想对结构列表进行操作,传递 a 还不够Struct*
吗?这样我可以struct++
解决下一个结构,还是我在这里很困惑?:)
如果我想以某种方式重新排列结构列表,它不是很有用吗?但是,如果我只是阅读,我不明白这一点。
这取决于您的数据结构是什么样的。假设这p
是一个以空结尾的指针数组struct s
,您可以使用这样的循环运行它:
void f(struct s **p)
{
while (*p != NULL) {
/* some stuff */
(*p)++;
}
}
通常,仅当您尝试修改指针本身时,使用指向指针的指针才有用。
这种参数有很多用途......
一个已经提到的并且很常见的是允许调用者使用函数来修改指针。这里最明显的情况是在获取一些数据时......
void getData( void** pData, int* size )
{
*pData = getMyDataPointer();
*size = getMyDataSize();
}
另一种选择是,也许额外的间接级别允许列表以某种方式运行?例如,通过使用索引来引用特定元素,它们可以被分配和重新分配,而不会有悬空指针的风险。
另一种选择是列表非常大并且存在于碎片内存中,或者被快速访问,因此列表实际上是几个组合在一起的较小列表。这种技术也可以用来“懒惰地”分配巨大的数组,例如为十亿个元素的数组提供一个接口,然后根据需要分配 100k 的块,因为它们是用指向整体的 struct** 读取/写入的东西,每个 struct* 要么为空,要么指向 100k 结构......
老实说,上下文非常重要......三重指针作为函数参数也有很多用途,遵循类似的推理。(例如,将我提到的第一件事与第二件事结合起来,或者将第二件事与第三件事结合起来,等等)
如果你想修改调用者中传递给这个函数的指针,你通常会这样做。
因为,在 C 中一切都是按值传递的,传递struct*
只会传递指针的副本,不会修改调用者中的指针。此C-FAQstruct *
中解释了为什么通过。
如果您不打算修改调用者中的指针,则无需传递struct **
.
API 的创建者可能认为,如果每个函数的第一个参数都相同,则参数列表会更容易记住。
您是对的,除非您的函数旨在修改传入的指针,否则没有理由将指针传递给指针。在访问struct
s 数组的情况下,单级间接绝对足够了。