在C语言中什么时候应该使用双重间接?谁能举个例子解释一下吗?
我所知道的是双间接是指向指针的指针。为什么我需要指向指针的指针?
在C语言中什么时候应该使用双重间接?谁能举个例子解释一下吗?
我所知道的是双间接是指向指针的指针。为什么我需要指向指针的指针?
当前回答
假设你有一个指针。取值为地址。 但现在你想更改地址。 你可以。通过执行pointer1 = pointer2,你给了pointer1一个pointer2的地址。 但是!如果在函数中执行此操作,并且希望结果在函数完成后仍然存在,则需要做一些额外的工作。你需要一个新的pointer3来指向pointer1。将指针3传递给函数。 这里有一个例子。先看看下面的输出,以便理解。
#include <stdio.h>
int main()
{
int c = 1;
int d = 2;
int e = 3;
int * a = &c;
int * b = &d;
int * f = &e;
int ** pp = &a; // pointer to pointer 'a'
printf("\n a's value: %x \n", a);
printf("\n b's value: %x \n", b);
printf("\n f's value: %x \n", f);
printf("\n can we change a?, lets see \n");
printf("\n a = b \n");
a = b;
printf("\n a's value is now: %x, same as 'b'... it seems we can, but can we do it in a function? lets see... \n", a);
printf("\n cant_change(a, f); \n");
cant_change(a, f);
printf("\n a's value is now: %x, Doh! same as 'b'... that function tricked us. \n", a);
printf("\n NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a' \n");
printf("\n change(pp, f); \n");
change(pp, f);
printf("\n a's value is now: %x, YEAH! same as 'f'... that function ROCKS!!!. \n", a);
return 0;
}
void cant_change(int * x, int * z){
x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", x);
}
void change(int ** x, int * z){
*x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", *x);
}
以下是输出:(先阅读这个)
a's value: bf94c204
b's value: bf94c208
f's value: bf94c20c
can we change a?, lets see
a = b
a's value is now: bf94c208, same as 'b'... it seems we can, but can we do it in a function? lets see...
cant_change(a, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c208, Doh! same as 'b'... that function tricked us.
NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a'
change(pp, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c20c, YEAH! same as 'f'... that function ROCKS!!!.
其他回答
我经常使用它们的一件事是,当我有一个对象数组,我需要根据不同的字段对它们执行查找(二进制搜索)。 我保留原始数组…
int num_objects;
OBJECT *original_array = malloc(sizeof(OBJECT)*num_objects);
然后创建一个指向对象的排序指针数组。
int compare_object_by_name( const void *v1, const void *v2 ) {
OBJECT *o1 = *(OBJECT **)v1;
OBJECT *o2 = *(OBJECT **)v2;
return (strcmp(o1->name, o2->name);
}
OBJECT **object_ptrs_by_name = malloc(sizeof(OBJECT *)*num_objects);
int i = 0;
for( ; i<num_objects; i++)
object_ptrs_by_name[i] = original_array+i;
qsort(object_ptrs_by_name, num_objects, sizeof(OBJECT *), compare_object_by_name);
您可以根据需要创建任意数量的已排序指针数组,然后对已排序指针数组使用二进制搜索,根据已有的数据访问所需的对象。对象的原始数组可以保持无序,但是每个指针数组将按照它们指定的字段进行排序。
假设你有一个指针。取值为地址。 但现在你想更改地址。 你可以。通过执行pointer1 = pointer2,你给了pointer1一个pointer2的地址。 但是!如果在函数中执行此操作,并且希望结果在函数完成后仍然存在,则需要做一些额外的工作。你需要一个新的pointer3来指向pointer1。将指针3传递给函数。 这里有一个例子。先看看下面的输出,以便理解。
#include <stdio.h>
int main()
{
int c = 1;
int d = 2;
int e = 3;
int * a = &c;
int * b = &d;
int * f = &e;
int ** pp = &a; // pointer to pointer 'a'
printf("\n a's value: %x \n", a);
printf("\n b's value: %x \n", b);
printf("\n f's value: %x \n", f);
printf("\n can we change a?, lets see \n");
printf("\n a = b \n");
a = b;
printf("\n a's value is now: %x, same as 'b'... it seems we can, but can we do it in a function? lets see... \n", a);
printf("\n cant_change(a, f); \n");
cant_change(a, f);
printf("\n a's value is now: %x, Doh! same as 'b'... that function tricked us. \n", a);
printf("\n NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a' \n");
printf("\n change(pp, f); \n");
change(pp, f);
printf("\n a's value is now: %x, YEAH! same as 'f'... that function ROCKS!!!. \n", a);
return 0;
}
void cant_change(int * x, int * z){
x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", x);
}
void change(int ** x, int * z){
*x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", *x);
}
以下是输出:(先阅读这个)
a's value: bf94c204
b's value: bf94c208
f's value: bf94c20c
can we change a?, lets see
a = b
a's value is now: bf94c208, same as 'b'... it seems we can, but can we do it in a function? lets see...
cant_change(a, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c208, Doh! same as 'b'... that function tricked us.
NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a'
change(pp, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c20c, YEAH! same as 'f'... that function ROCKS!!!.
为什么是双指针?
目标是使用函数改变studentA所指向的对象。
#include <stdio.h>
#include <stdlib.h>
typedef struct Person{
char * name;
} Person;
/**
* we need a ponter to a pointer, example: &studentA
*/
void change(Person ** x, Person * y){
*x = y; // since x is a pointer to a pointer, we access its value: a pointer to a Person struct.
}
void dontChange(Person * x, Person * y){
x = y;
}
int main()
{
Person * studentA = (Person *)malloc(sizeof(Person));
studentA->name = "brian";
Person * studentB = (Person *)malloc(sizeof(Person));
studentB->name = "erich";
/**
* we could have done the job as simple as this!
* but we need more work if we want to use a function to do the job!
*/
// studentA = studentB;
printf("1. studentA = %s (not changed)\n", studentA->name);
dontChange(studentA, studentB);
printf("2. studentA = %s (not changed)\n", studentA->name);
change(&studentA, studentB);
printf("3. studentA = %s (changed!)\n", studentA->name);
return 0;
}
/**
* OUTPUT:
* 1. studentA = brian (not changed)
* 2. studentA = brian (not changed)
* 3. studentA = erich (changed!)
*/
这里的大多数答案或多或少都与应用程序编程有关。下面是一个嵌入式系统编程的例子。例如,以下是NXP Kinetis KL13系列微控制器参考手册的摘录,此代码片段用于从固件中运行驻留在ROM中的引导加载程序:
" 为了获得入口点的地址,用户应用程序读取包含引导加载程序API树指针的单词,该指针位于引导加载程序向量表的0x1C偏移量处。向量表被放置在引导加载器地址范围的底部,ROM的地址范围是0x1C00_0000。因此,API树指针位于地址0x1C00_001C。
引导加载程序API树是一个包含指向其他结构的指针的结构,这些结构具有引导加载程序的函数和数据地址。引导加载程序入口点总是API树的第一个单词。 "
uint32_t runBootloaderAddress;
void (*runBootloader)(void * arg);
// Read the function address from the ROM API tree.
runBootloaderAddress = **(uint32_t **)(0x1c00001c);
runBootloader = (void (*)(void * arg))runBootloaderAddress;
// Start the bootloader.
runBootloader(NULL);
一个原因是你想要改变传递给函数的作为函数参数的指针的值,要做到这一点,你需要指针指向指针。
简单地说,当你想在函数调用之外保留(或保留)内存分配或分配的变化时,使用**。(因此,传递带有双指针arg的函数。)
这可能不是一个很好的例子,但会告诉你基本的用法:
#include <stdio.h>
#include <stdlib.h>
void allocate(int **p)
{
*p = (int *)malloc(sizeof(int));
}
int main()
{
int *p = NULL;
allocate(&p);
*p = 42;
printf("%d\n", *p);
free(p);
}