在C语言中什么时候应该使用双重间接?谁能举个例子解释一下吗?
我所知道的是双间接是指向指针的指针。为什么我需要指向指针的指针?
在C语言中什么时候应该使用双重间接?谁能举个例子解释一下吗?
我所知道的是双间接是指向指针的指针。为什么我需要指向指针的指针?
当前回答
例如,如果您想随机访问不连续的数据。
p -> [p0, p1, p2, ...]
p0 -> data1
p1 -> data2
——用C
T ** p = (T **) malloc(sizeof(T*) * n);
p[0] = (T*) malloc(sizeof(T));
p[1] = (T*) malloc(sizeof(T));
存储一个指针p,它指向一个指针数组。每个指针指向一段数据。
如果sizeof(T)很大,则可能无法分配sizeof(T) * n字节的连续块(即使用malloc)。
其他回答
简单的例子,你可能已经见过很多次了
int main(int argc, char **argv)
在第二个参数中有它:指向char的指针的指针。
注意,指针表示法(char* c)和数组表示法(char c[])在函数参数中是可互换的。所以你也可以写char *argv[]。换句话说,char *argv[]和char **argv是可互换的。
上面所代表的实际上是一个字符序列数组(在启动时给予程序的命令行参数)。
有关上述函数签名的更多详细信息,请参见此回答。
字符串是使用双指针的一个很好的例子。字符串本身是一个指针,所以任何时候你需要指向一个字符串,你就需要一个双指针。
1. 基本概念-
当你申报如下:-
1. Char *ch -(称为字符指针) - ch为单个字符的地址。 - (*ch)将解引用字符的值。
2. Char **ch - 'ch'包含字符指针数组的地址。(如1) '*ch'包含单个字符的地址。(注意它与1不同,因为声明不同)。 (**ch)将解引用到字符的确切值..
添加更多指针将扩展数据类型的维度,从字符扩展到字符串,再扩展到字符串数组,等等……你可以把它和一维,二维,三维矩阵联系起来。
指针的用法取决于你如何声明它。
这是一个简单的代码..
int main()
{
char **p;
p = (char **)malloc(100);
p[0] = (char *)"Apple"; // or write *p, points to location of 'A'
p[1] = (char *)"Banana"; // or write *(p+1), points to location of 'B'
cout << *p << endl; //Prints the first pointer location until it finds '\0'
cout << **p << endl; //Prints the exact character which is being pointed
*p++; //Increments for the next string
cout << *p;
}
2. 双指针的另一个应用 (这也包括引用传递)
假设您想从函数中更新一个字符。如果你尝试以下方法:-
void func(char ch)
{
ch = 'B';
}
int main()
{
char ptr;
ptr = 'A';
printf("%c", ptr);
func(ptr);
printf("%c\n", ptr);
}
输出为AA。这是行不通的,因为您已经将“按值传递”传递给了函数。
正确的做法是-
void func( char *ptr) //Passed by Reference
{
*ptr = 'B';
}
int main()
{
char *ptr;
ptr = (char *)malloc(sizeof(char) * 1);
*ptr = 'A';
printf("%c\n", *ptr);
func(ptr);
printf("%c\n", *ptr);
}
现在扩展这个要求,更新字符串而不是字符。 为此,需要将函数中的形参作为双指针接收。
void func(char **str)
{
strcpy(str, "Second");
}
int main()
{
char **str;
// printf("%d\n", sizeof(char));
*str = (char **)malloc(sizeof(char) * 10); //Can hold 10 character pointers
int i = 0;
for(i=0;i<10;i++)
{
str = (char *)malloc(sizeof(char) * 1); //Each pointer can point to a memory of 1 character.
}
strcpy(str, "First");
printf("%s\n", str);
func(str);
printf("%s\n", str);
}
在本例中,method使用双指针作为参数来更新字符串的值。
我今天看到了一个很好的例子,从这篇博客文章,我总结如下。
假设您有一个链表中节点的结构,可能是这样
typedef struct node
{
struct node * next;
....
} node;
现在您想实现一个remove_if函数,它接受删除条件rm作为参数之一,并遍历链表:如果一个条目满足该条件(例如rm(entry)==true),它的节点将从链表中删除。最后,remove_if返回链表的头(可能与原始头不同)。
你可以写信
for (node * prev = NULL, * curr = head; curr != NULL; )
{
node * const next = curr->next;
if (rm(curr))
{
if (prev) // the node to be removed is not the head
prev->next = next;
else // remove the head
head = next;
free(curr);
}
else
prev = curr;
curr = next;
}
就像你的for循环。这里的信息是,如果没有双指针,您必须维护一个prev变量来重新组织指针,并处理两种不同的情况。
但是使用双指针,你实际上可以写
// now head is a double pointer
for (node** curr = head; *curr; )
{
node * entry = *curr;
if (rm(entry))
{
*curr = entry->next;
free(entry);
}
else
curr = &entry->next;
}
你现在不需要一个prev,因为你可以直接修改什么prev->next指向。
为了使事情更清楚,让我们稍微跟随一下代码。拆卸过程中:
如果entry ==* head:它将是*head (==*curr) =* head->next - head现在指向新标题节点的指针。您可以通过直接将head的内容更改为一个新的指针来实现这一点。 如果entry != *head:类似地,*curr是prev->next所指向的,现在指向entry->next。
无论哪种情况,您都可以使用双指针以统一的方式重新组织指针。
例如,如果您想随机访问不连续的数据。
p -> [p0, p1, p2, ...]
p0 -> data1
p1 -> data2
——用C
T ** p = (T **) malloc(sizeof(T*) * n);
p[0] = (T*) malloc(sizeof(T));
p[1] = (T*) malloc(sizeof(T));
存储一个指针p,它指向一个指针数组。每个指针指向一段数据。
如果sizeof(T)很大,则可能无法分配sizeof(T) * n字节的连续块(即使用malloc)。