将双指针作为参数传递

3

我想使用双指针。但是,请告诉我我在这里做错了什么。函数调用后,值n没有更新。我期望看到30,但仍然看到10。

int main(int argc, char **argv) {
    int n = 10;
    int *ptr = &n;
    int **ptr2ptr = &ptr;
    function(&ptr2ptr);
    printf("%d", n);
    return 0;
}

void function(int *num) {
    *num = 30; 
}

这是整个代码吗? - Iharob Al Asimi
1
我认为那是一个三级指针。好久没见过了。 :D - Haris
4
好的,我会尽力将其翻译成通俗易懂的中文,并保持原意不变。需要翻译的内容是:"Also, uh, don't forget your function prototype." - Kanga_Roo
1
这段代码能编译吗?你正在将三级指针传递给一个接受单个指针的函数。 - Code-Apprentice
@Code-Apprentice:在调用之前未声明该函数,过时的语义导致隐式声明了一个“int function()”函数,该函数接受任意数量和类型的参数,返回一个“int”。 - chqrlie
显示剩余2条评论
9个回答

6

您实际上将一个三重间接整数传递给函数function&ptr2ptr是指向整数指针的指针的地址。在从main调用function之前,您没有定义也没有声明function。这在C99中是不正确的,但在ANSI C中得到支持,并隐式地声明function需要任意数量和类型的参数并返回int。您应该将function的定义移到main之前,并更改为:

void function(int ***num) {
    ***num = 30; 
}

解决问题时尽可能少地更改原始代码,但也会鼓励OP成为3星级程序员,即使他不需要。 - ForeverStudent

3
您正在使用&ptr2ptr传递三级指针,而不是*ptr2ptr,并且您的函数接受指针而不是指向指针的指针(int *而不是int **)。
另一种看待它的方式是&ptr2ptr获取指针的地址,而不是对其进行解引用。您想要的是:
function(*ptr2ptr);

为了让你更好地理解错误,我走了一条较长的路 - 你可以查看这个更新的代码,并阅读注释以获取更多信息。

记住,在 C 语言中:"使用 == 声明"

这意味着声明中的 * 创建一个指针,而使用中的 * 解引用(使用)一个指针。

& 将返回对象的地址。

以下是一些代码以展示它们之间的不同:

int main(int argc, char **argv) {
    int n = 10;
    int *ptr = &n; // this is a pointer to an int
    int **ptr2ptr = &ptr; // this is a pointer to the pointer
    // &ptr2ptr is a triple pointer - so we use the double pointer instead.
    function(ptr2ptr);
    // we could have used the original function using:
    // function(*ptr2ptr);
    printf("%d", n);
    return 0;
}

// `int *num ` in your function prototype
// is referencing a pointer to a pointer,
// but it expects a double pointer - updated:
void function(int **num) {
    // *num dereferences the first layer
    // **num references the actual number.
    **num = 30;
    // or:
    // *num = &30; // will fail to compile, unless 30 was a variable
}

*num = &30 确实会编译失败,不仅因为缺少 ; ;-) - chqrlie
@chqrlie 哈哈哈,没错 :-) 如果30是动态分配的,使用双指针会更有意义... 但它是一个没有地址可以调用的常数,所以是会失败的 :) - Myst

2

由于您正在更新传递给函数的指针所指向的值,因此不需要传递指向指针的指针(实际上您正在传递指向指针的指针)。
函数function期望int *类型,因此只需传递ptr即可。您必须更改函数调用。

function(&ptr2ptr);  

to

function(ptr);  

除此之外,你应该在 main 函数之前包含函数 function 的函数原型或定义。


2
#include <stdio.h>

void function(int** num)
{
    **num = 30;
}

int main(int argc, char**argv)
{
    int n = 10;
    int* ptr = &n;
    int** ptr2ptr = &ptr;
    function(ptr2ptr);
    printf("%d\n",n);
    return 0;
}

请描述您的更改如何回答OP的问题。 - Code-Apprentice

2

您需要使用正确的输入类型来实现函数:int**。

如果您添加一些gcc标志,例如-pedantic,您将看到在类型方面犯了一些错误。

一个可工作的版本是:

#include <stdio.h>

void function(int** num);

int main(int argc, char**argv) {
    int n = 10;
    int* ptr = &n;
    int** ptr2ptr = &ptr;
    function(ptr2ptr);
    printf("%d",n);
    return 0;
}

void function(int** num)
{
    **num = 30;
}

请注意,您不需要双指针来实现所需操作,一个简单的指针就足够了。

2
让我为您评论代码并解释其中的含义:
int main(int argc, char **argv) {

    int n = 10; //declaring variable n type int

    //declaring variable ptr type int * setting it to address of n
    int *ptr = &n;  

    //declaring variable ptr2ptr as int** and setting it to address of ptr
    int **ptr2ptr = &ptr;

    //now you are trying to take the address of ptr2ptr, which is the address of an int**
    //this gives you an int***, you are passing this in function with undesirable behaviour
    function(&ptr2ptr);
    printf("%d", n);
    return 0;
}

void function(int *num) //take in a parameter of type int*
{
    *num = 30; //dereference it and put value 30 in it
}

不要调用function(&ptr2ptr),而应该调用function(*ptr2ptr)或者更好的方式是function(ptr)


2

让我们仔细看一下你代码中的每一行:

int main(int argc, char **argv) {
    int n = 10;

n 被声明为一个 int

    int *ptr = &n;

ptr 声明为一个指向整数的指针,并被赋予 n 的地址。

    int **ptr2ptr = &ptr;

ptr2ptr被声明为指向指针的指针,并被赋予ptr的地址。这就是我认为你所称的“双重指针”。

    function(&ptr2ptr);

现在,您将ptr2ptr的地址发送到function()。请注意,您试图传递给function()的值是指向指针的指针的指针(即“三级指针”)。
    printf("%d", n);
    return 0;
}

void function(int *num) {

function()被声明为接受一个指向整数的指针。这意味着在main()中调用函数应该会导致编译器错误,因为参数类型与参数类型不匹配。

    *num = 30; 
}

正如我上面所描述的那样,你的代码不应该编译。你正在向一个只接受单个指针 (int*) 的函数传递一个三级指针 (int***)。你至少有三个可能的解决方案:

  1. Declare function() to take a triple pointer:

    void function(int*** num) {
        ***num = 30; 
    }
    
  2. Declare function() to take a double pointer:

    void function(int **num) { 
        **num = 30; 
    }
    

    and change the function call in main to

    function(ptr2ptr);
    
  3. Both of these seem completely unnecessary since you are only trying to change the value of a single int. This means you can do all of what you want with a single pointer:

    void function(int *num) { 
        *num = 30; 
    }
    

    Now you can call this function with either

    function(ptr);
    

    or

    function(&num);
    

2

您的函数 void function(int *num) 接受1个参数,即指向 int 的指针,因此在调用它时,您应该提供一个整数的地址,而不是指向 int 的指针的地址,也不是指向指向 int 的指针的地址。

int main(int argc, char **argv) {
    int n = 10;
    int *ptr = &n;
    int **ptr2ptr = &ptr;
    function(&n);
    // function(ptr)  /* this also works */
    printf("%d", n);
    return 0;
}

void function(int *num) {
    *num = 30; 
}

0
void function(int ***num) {
  ***num = 30; 
}

int main(int argc, char **argv) {
  int n = 10;
  int *ptr = &n;
  int **ptr2ptr = &ptr;
  function(&ptr2ptr);
  printf("%d", n);
  return 0;
}

你所做的是给出了双指针的地址,因此它变成了三级指针。按照上述方法操作可以正常工作。

由于使用三级指针可能会使代码变得复杂,因此最好只使用双指针而不是发送双指针的地址:

void function(int **num) {
  **num = 30; 
}

int main(int argc, char **argv) {
  int n = 10;
  int *ptr = &n;
  int **ptr2ptr = &ptr;
  function(ptr2ptr);
  printf("%d", n);
  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接