【问题标题】:Changing address contained by pointer using function使用函数更改指针包含的地址
【发布时间】:2021-06-10 15:42:18
【问题描述】:

如果我将指针p 声明为int *p;在主模块中,我可以通过分配p = &a; 来更改p 包含的地址,其中a 是另一个已经声明的整数变量。 我现在想通过以下函数更改地址:

void change_adrs(int*q)
{
    int *newad;
    q = newad;
}

如果我从主模块调用这个函数

int main()
{
    int *p;
    int a = 0;
    p = &a; // this changes the address contained by pointer p
    printf("The address is %u\n", p);
    change_adrs(p);
    printf("The address is %u\n", p); // but this doesn't change the address
    return 0;
}

地址内容不变。对同一任务使用函数有什么问题?

【问题讨论】:

  • 您是按值传递指针。如果您需要更改函数内部的指针,请按引用传递...双指针。

标签: c function pointers


【解决方案1】:

这不会改变p 的实际值,因为函数中的q 是本地的,并且该函数中的更改不会反映在main 中,所以传递p 的地址而不是传递@ 987654325@按价值计算

在下面使用这个语法

void change_adrs(int **q)
{
    int * otheraddess;
    *q = otheraddress; 
}

然后像这样打电话change_adrs(&p);

或者,您还有其他方法: 改变函数的返回类型并捕获返回的地址。

int* change_adrs(int *q)
{
    int * otheraddess;
    q = otheraddress;
    return q; 
}


int main()
{
    p = change_adrs(p);
    return 0;
}

【讨论】:

    【解决方案2】:

    在 C 中,函数参数是按值传递的。因此,对您的参数进行了复制,并且对该副本进行了更改,而不是您期望看到修改的实际指针对象。如果您想这样做,您将需要更改您的函数以接受指针到指针的参数并更改取消引用的参数。 例如

     void foo(int** p) {
          *p = NULL;  /* set pointer to null */
     }
     void foo2(int* p) {
          p = NULL;  /* makes copy of p and copy is set to null*/
     }
    
     int main() {
         int* k;
         foo2(k);   /* k unchanged */
         foo(&k);   /* NOW k == NULL */
     }
    

    如果您有幸使用 C++,另一种方法是更改​​函数以接受对指针的引用。

    【讨论】:

    • 我只想指出,C 标准不保证将 p 赋值为 0 会使其为空。
    • 如果我要在被调用函数中*arr = malloc()一个新数组并将**p指向它,是*p = &arr吗?
    • @JKRT:C 规范中的 6.2.3.2 表示“值为 0 的整数常量表达式,或转换为 void * 类型的此类表达式称为空指针常量。” -- 所以分配一个文字 0 会使它为空。该句子中的“或”表示不需要强制转换。
    【解决方案3】:

    如果你想在C语言的函数中改变一个变量的内容,指针也是一种变量,你必须通过指针间接引用 始终使用& 地址和* 取消引用运算符。我的意思是 * 运算符在更改变量的值时总是被使用和放在前面。

    #include <stdio.h>
    #include <stdlib.h>
    
    
    void changeIntVal(int *x) {
        *x = 5;
    }
    
    void changePointerAddr(int **q) {
        int *newad;
        *q = newad;
    }
    
    void changePPAddr(int ***q) {
        int **dummy;
        *q = dummy;
    }
    
    int main() {
        int *p;
        int **pp;
        int *tempForPP;
        int a = 0;
        printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
    
    
        p = &a;
        pp = &tempForPP;
        printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
    
        changeIntVal(&a);        // ----
                                 //    |---
        changePointerAddr(&p);   // ----  |---->  parts of what I mean
                                 //    |---
        changePPAddr(&pp);       // ----
    
        printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
    
        return 0;
    
    }
    

    【讨论】:

      【解决方案4】:

      对于像int 这样的原始数据类型,双指针不是必需的。您可以直接写入存储int 的地址,将其地址视为被调用函数中的指针。这与char 数组(“字符串”)不同,其中指向的大小是可变的,因此在从被调用函数中更改它时必须使用另一级间接。试试这个:

      void foo(int *oldVal)
      {
          int newVal = 99;    // or whatever you want
          *oldVal = newVal;
      }
      
      int main(int argc, char *argv[])
      {
          int someVal = 0;
          foo(&someVal);      // we send its address to foo()
      
          printf("someVal is now %d.\n", someVal);
      
          return EXIT_SUCCESS;
      }
      

      【讨论】:

      • 这不是对问题的回应!,他要求更改指针地址而不是指针值
      【解决方案5】:

      在 C 中,变量是按值传递的——指针的副本被传递给函数。改用另一个指向该指针的指针:

      void change(int **p, int *someOtherAddress)
      {
          *p = someOtherAddress;
      }
      
      int a = 1, b = 2;
      int *p = &a;
      
      printf("*p = %d\n", *p);
      change(&p, &b);
      printf("*p = %d\n", *p);
      

      打印出来

      *p = 1
      *p = 2
      

      【讨论】:

      • 赞成纯粹是因为这个答案避免了短语“双指针”
      猜你喜欢
      相关资源
      最近更新 更多