【问题标题】:Pointer to pointer argument variable and how they work? e.g. function(int **ptr)指向指针参数变量的指针以及它们如何工作?例如函数(int **ptr)
【发布时间】:2018-08-10 11:25:50
【问题描述】:

我正在编写代码来了解在函数中将指针作为参数传递时会发生什么。

void ptrTest(int **arg_ptr); 

int main() {
    int some_var = 5;
    int *ptr1;
    ptr1 = &some_var;

    printf("Address of some_var: %u\n\n", &some_var);
    printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
    printf("Address of *ptr1 variable: %u\n\n", &ptr1);
    ptrTest(ptr1);
}

void ptrTest(int **arg_ptr){
    printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);    
}

结果如下:

Address of some_var: 3119323004

Value stored in *ptr1 (references to some_var): 3119323004
Address of *ptr1 variable: 3119322992

Value stored in **arg_ptr (references to some_var): 3119323004

我很惊讶 arg_ptr 采用了引用 some_var 地址的值。我期待 **arg_ptr 指向 *ptr 并存储 3119322992 的值(引用 *ptr 的地址)。

当我测试指向函数外部指针的指针时,它确实以这种精确的方式运行。为什么将指针作为参数的指针不同让我感到困惑。

你能解释一下这里发生了什么吗?

【问题讨论】:

  • 我很惊讶编译器没有抱怨参数 (int *) 与类型 (int **) 不匹配
  • @SaileshD 所说的 :) 符合标准的编译器必须在此处为您提供诊断消息。投票结束这是一个简单的错字。
  • 您的输出不正确。您永远不会在代码中打印"Value stored in"。请复制并粘贴您的代码和输出。不要提供从内存中重写的随机代码。
  • 真实代码,但为了清楚起见更改了字符串 printf 并忘记更改代码。现在更新了。

标签: c function pointers


【解决方案1】:

首先什么是指针? C/C++ 中的指针就像任何其他类型的变量一样,如 int、char 等。但这个变量的特点是与其他变量不同,它只保存内存位置的地址。同样,该内存位置也可能是指针变量或任何其他常规变量(int 或 char)。

现在什么是指针指针?一个变量可以存储指针变量的地址,而该指针变量可能保存另一个变量的地址,例如:-

 int i = 10; //`i` is assign with a value  10 and `i` has its own address which we can get by `&i`;

 int *ptr1 = &i;// now ptr1 is pointer to `i` means ptr1 is assign with the
 //address of `i` hence if we dereference the address of *ptr1 we will get the value stored at that memory location

现在是你的情况

 void ptrTest(int **arg_ptr){
    printf("Address store in of **arg_ptr: %u\n",arg_ptr);    
}

所以它会像下面这样工作

int **arg_ptr = ptr1;//Wrong, `ptr1` is assign to `arg_ptr`, which is wrong because `arg_ptr` is a pointer to pointer type

所以这里你应该存储一个指针的地址,但你存储的是一个变量 int 的地址,它是i。 因为i 的地址已经在语句 int *ptr1 = &i; 中赋值。到ptr1。 正确的分配是

arg_ptr = &ptr1; //address of a pointer not address of a int variable.

现在首先取消引用:-

  *arg_ptr; //value of a pointer ptr1 that means address of `i`

 *(*arg_ptr); or **arg_ptr;// we further dereferenced the address of ptr1 here, which is value 10

现在你应该像下面这样调用你的函数:-

ptrTest(&ptr1);// address of a pointer.

【讨论】:

    【解决方案2】:

    ptrTest 需要 int ** 类型的参数,但您传递的是 int*。你的编译器应该抱怨。您需要将ptr 的地址传递给函数。

    ptrTest(&ptr1);  
    

    除此之外,您应该使用%p 规范来打印地址。

    printf("Address of some_var: %p\n\n", (void*)&some_var);
    

    【讨论】:

      【解决方案3】:

      当我编译你的代码时,我得到一长串错误:

      "test.c", line 11: warning #2181-D: argument is incompatible with
                corresponding format string conversion
            printf("Address of some_var: %u\n\n", &some_var);
                                                  ^
      
      "test.c", line 12: warning #2181-D: argument is incompatible with
                corresponding format string conversion
            printf("Value stored in *ptr1 (references to some_var): %u\n", ptr1);
                                                                           ^
      
      "test.c", line 13: warning #2181-D: argument is incompatible with
                corresponding format string conversion
            printf("Address of *ptr1 variable: %u\n\n", &ptr1);
                                                        ^
      
      "test.c", line 14: warning #2167-D: argument of type "int *" is incompatible
                with parameter of type "int **"
            ptrTest(ptr1);
                    ^
      
      "test.c", line 18: warning #2181-D: argument is incompatible with
                corresponding format string conversion
            printf("Value stored in **arg_ptr (references to some_var): %u\n",arg_ptr);
      

      让我们重写这段代码,让它编译没有错误,也许更清晰一点:

      #include <stdio.h>
      
      void ptrTest(int **arg_ptr)
        {
        printf("Value stored in arg_ptr (points to ptr1): %#p\n", arg_ptr);
        printf("Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): %#p\n", *arg_ptr);
        printf("Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): %d\n", **arg_ptr);
        }
      
      int main()
        {
        int some_var = 5;
        int *ptr1;
      
        ptr1 = &some_var;
      
        printf("some_var: %d\n", some_var);
        printf("Address of some_var: %#p\n\n", &some_var);
        printf("Value stored in ptr1 (should be address of some_var): %#p\n", ptr1);
        printf("Address of ptr1 variable: %#p\n\n", &ptr1);
        ptrTest(&ptr1);
        }
      

      发生了什么变化:

      1. 在 printf (%d) 中使用有符号 int 格式而不是无符号格式 (%u)。

      2. 打印指针时使用 printf (%p) 中的指针格式。

      3. 已将代码添加到 ptrTest 以跟随 arg_ptr 一直回到 指针链的基目标。

      4. 添加了打印some_var值的代码

      5. 更改了输出的措辞,以阐明显示的内容以及应匹配的值。

      新版本编译无误(HP-UX默认C编译器)。

      当新版本运行时,会打印以下输出:

      some_var: 5
      Address of some_var: 0x7fffecd0
      
      Value stored in ptr1 (should be address of some_var): 0x7fffecd0
      Address of ptr1 variable: 0x7fffecd4
      
      Value stored in arg_ptr (points to ptr1): 0x7fffecd4
      Value pointed to by arg_ptr (i.e. *arg_ptr - should be same as ptr1): 0x7fffecd0
      Value pointed to by *arg_ptr (i.e. **arg_ptr - should be same as some_var): 5
      

      现在您可以前后跟踪指针链,查看哪个指针指向哪个值,以及它们是如何链接的。

      祝你好运。

      【讨论】:

      • 好多了!按照你写的内容进行编译,没有错误和警告。干杯。
      猜你喜欢
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多