简体   繁体   English

这两种声明指针的方式有什么区别?

[英]What is the difference between these 2 ways of declaring a pointer to pointer?

Have a look at this code snippet: 看一下以下代码片段:

int i = 10;
int *pi = &i;
int **ppi = π // first declaration
int *api = pi;   // second declaration

printf("i's value is: %d\n",i);
printf("pi's value is: %d\n",*pi);
printf("ppi's value is: %d, at the address: %d\n",**ppi);
printf("api's value is: %d, at the address: %d\n",*api);

Output 产量

$ ./test
i's value is: 10
pi's value is: 10
ppi's value is: 10, at the address: 2686760
api's value is: 10, at the address: 2686760

So which way is (perhaps) more preferrable in those 2 declarations of pointer to pointer, and is there any technical difference between those two? 那么在这两个指向指针的指针声明中,哪种方法(也许)更可取,并且这两者之间在技术上有什么不同?

Technically, you've only declared one pointer-to-pointer. 从技术上讲,您仅声明了一个指针到指针。

int **ppi = π // first declaration

The second declaration is just a pointer which, when assigned, gets a copy of the first pointer pi 's address. 第二个声明只是一个指针,分配该指针时,将获得第一个指针pi的地址的副本。

Here's how you can prove it; 这是您可以证明的方式; after your test code, add this: 在您的测试代码之后,添加以下内容:

int i2 = 20;
pi = &i2;

printf("ppi's value is: %d, at the address: %d\n",**ppi,*ppi);
printf("api's value is: %d, at the address: %d\n",*api,api);

The output will be: 输出将是:

ppi's value is: 20, at the address: 2686764 (or some other address)
api's value is: 10, at the address: 2686760

When you change the value of pi (what it points to), dereferencing ppi will reflect the changes, as it points to pi , but because api was just made as a copy of pi before it changed, it will continue pointing to i . 当您更改pi的值(它指向的内容)时,取消引用ppi会反映更改,因为它指向pi ,但是由于api在更改之前只是作为pi的副本制作的,因此它将继续指向i

The second one ( api ) doesn't declare a pointer to pointer. 第二个( api )没有声明指向该指针的指针。 It creates a pointer to int, and initializes it with the value of another pointer to int. 它创建一个指向int的指针,并使用另一个指向int的指针的值对其进行初始化。

Your last two printf s ( ppi and api ) are missing their second argument, so it's printing whatever happens to be in the stack where said argument should be (compiling with appropriate warnings would have caught this). 您的最后两个printfppiapi )缺少第二个参数,因此它将打印该参数应在堆栈中的任何内容(使用适当的警告进行编译将捕获此问题)。 api is NOT a pointer to a pointer, it's a pointer to an int , same as pi . api不是指向指针的指针,而是指向piint指针。 The ONLY way to declare a pointer to a pointer (ignoring spacing and parentheses styles) is type **var . 声明指针的指针(忽略空格和括号样式)的唯一方法是type **var

The types defined the semantics of how you interact the data, you should not ever assign a pointer to int directly to a pointer to a pointer of an int, for example. 这些类型定义了如何交互数据的语义,例如,永远不要直接将指向int的指针分配给指向int的指针的指针。 However you might be wondering a use case of using a ** type. 但是,您可能想知道使用**类型的用例。

For an example, look at this code I wrote: 例如,看一下我写的这段代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct fooStruct 
{
  int a;
  int b;
} FOO_STRUCT;

void multiReturns(int *a, FOO_STRUCT **b) {
  *a = 42;
  //b is a pointer that points to a FOO_STRUCT pointer
  if(*b) {
    free(*b);
    printf("Proof that we deleted memory.\n");
  }
  //This changes what b points to in main.
  *b = (FOO_STRUCT *)malloc(sizeof(FOO_STRUCT));
  printf("The new value of *b, this may or maynot be the same as before: %p\n", *b);
  //Parens for clarity, We dereferenced the pointer to the 
  //FOO_STRUCT pointer. Then, we derefrence the FOO_STRUCT
  //pointer to access its members.
  (*(*b)).a = 59;
  (*(*b)).b = 42;
  return;
}

int main(int argc, char **argv)
{
  int a = 0;
  FOO_STRUCT *b = (FOO_STRUCT *)malloc(sizeof(FOO_STRUCT));
  (*b).a = 1;
  (*b).b = 2;
  printf("BEFORE a = %d\n", a);
  printf("BEFORE b = %p\n", b);
  printf("BEFORE *b.a = %d\n", (*b).a);
  printf("BEFORE *b.b = %d\n", (*b).b);
  multiReturns(&a, &b);
  printf("AFTER a = %d\n", a);
  //The value AFTER b might have changed, depends on allocation factors..
  printf("AFTER b = %p\n", b);
  printf("AFTER *b.a = %d\n", (*b).a);
  printf("AFTER *b.b = %d\n", (*b).b);
  free(b);
  return 0;  
}

The output on my machine: 我机器上的输出:

[hart@katamari tests]$ gcc pointers.c -o ptr
[hart@katamari tests]$ ./ptr
BEFORE a = 0
BEFORE b = 0x19b41010
BEFORE *b.a = 1
BEFORE *b.b = 2
Proof that we deleted memory.
The new value of *b, this may or maynot be the same as before: 0x19b41010
AFTER a = 42
AFTER b = 0x19b41010
AFTER *b.a = 59
AFTER *b.b = 42

There are functions and the standard library, and elsewhere, that take a pointer to a pointer of a type. 有函数和标准库以及其他地方,它们使用指向类型指针的指针。 As long as a parameter of ** is not const qualified, it indicates that the value can be changed and it may, or maynot point to the same allocated memory. 只要**的参数不是const限定符,它表示可以更改该值,并且它可以或可以不指向同一分配的内存。 In my example I deleted the old pointer, but that is function specific you need to watch out for. 在我的示例中,我删除了旧的指针,但这是您需要注意的特定函数。 Also, if the caller is responsible to delete any new memory returned could also be function specific, so read the documentation of any functions you see that use these and make sure you document any that you write well. 另外,如果调用方负责删除返回的任何新内存,也可能是特定于函数的,因此请阅读使用这些函数的所有函数的文档,并确保对所有编写良好的文档进行记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将数组分配给指针时,这两种方式有什么区别 - What is the difference between that ways, when assign an array to pointer 指针和指针之间有什么区别 - What is the difference between pointer to pointer and a pointer 指向数组的指针和指向指针的指针有什么区别? - What is the difference between pointer to array and pointer to pointer? 指针和指针变量之间有什么区别? - What's the difference between a pointer, and a pointer variable? **pointer 和 &amp;pointer 作为函数参数有什么区别? - What is the difference between **pointer and &pointer as function parameter? 指向缓冲区的指针和指向文件的指针有什么区别? - What is the difference between a pointer to a buffer and a pointer to a file? 指针地址和双指针地址有什么区别 - What is the difference between address of pointer and double pointer 无法理解将指针 char *str 声明为 str/&amp;str 之间的区别?有什么区别,它有什么作用? - Can't understand the difference between declaring a pointer char *str as str/&str?Whats the difference and what does it do? 指向指针的指针和C中指针的地址有什么区别? - What is the difference between a pointer to a pointer and the addressof a pointer in C? 在函数参数列表中声明char指针和char数组有什么区别? - What is the difference between declaring an char pointer and an array of chars in a function parameter list?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM