函数

时间:2017-10-23 16:50:35

标签: c++ c pointers

我不明白函数在作为参数传递时如何更改指针的状态。例如,在此代码中 -

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

void inc(int* a) {
    a++;
}

void change(int* a) {
    a[0] = 2;
    a[1] = 3;
}

int main() {

    int* a = (int*) malloc(2 * sizeof(int));
    a[0] = 1;
    a[1] = 2;

    printf("%d \n",*a);
    inc(a);
    printf("%d \n",*a);

    change(a);
    return 0;
}

当我尝试使用函数inc()时,观察到指针不会递增。 但与此同时,change()实际上确实改变了指针的值。

你能解释为什么inc()不起作用吗?

6 个答案:

答案 0 :(得分:1)

这是画一些照片的好地方。当你写

int* a = (int*) malloc(2 * sizeof(int));

你得到一个如下所示的设置:

+---------+      +---------+---------+
| addr X  | ---> |  ?????  |  ?????  |
+---------+      +---------+---------+
 pointer a
  in main

将值分配给a[0]a[1]后,事情如下所示:

+---------+      +---------+---------+
| addr X  | ---> |    1    |    2    |
+---------+      +---------+---------+
 pointer a
  in main

现在,我们假设您致电inc(a)。这会将指针a的副本传递给inc函数。由于指针是唯一被复制的东西,所以现在看起来像这样:

+---------+      +---------+---------+
| addr X  | ---> |    1    |    2    |
+---------+      +---------+---------+
 pointer a            ^
  in main             |
                      |
+---------+           |
| addr X  |-----------+
+---------+
 pointer a
   in inc

请注意,现在有两个名为a的指针,但它们并不是同一个指针。如果你有两个叫Zoe的朋友 - 他们有相同的名字,但他们不是同一个人。

inc内,你写了

a++;

表示&#34;使指针a前进,指向当前指向的int下的+---------+ +---------+---------+ | addr X | ---> | 1 | 2 | +---------+ +---------+---------+ pointer a ^ in main | | +---------+ | | addr Y |---------------------+ +---------+ pointer a in inc 。&#34;这看起来像这样:

a

请注意maina的回复未更改,因为我们正在操作inc的副本。再回想一下Zoe的比喻 - 如果你和一个叫Zoe的人谈话,那并不意味着你和另一个叫Zoe的人交谈过。因此,当a返回时,+---------+ +---------+---------+ | addr X | ---> | 1 | 2 | +---------+ +---------+---------+ pointer a in main 的副本会消失在以太网中,我们就会离开:

inc

由于指针未更改,因此您在调用change之前和之后会看到相同的值。

但是调用change的方式不同。当您最初拨打+---------+ +---------+---------+ | addr X | ---> | 1 | 2 | +---------+ +---------+---------+ pointer a ^ in main | | +---------+ | | addr X |-----------+ +---------+ pointer a in change 时,情况如下:

a[0] = 2;

当你现在写

a

您正在说&#34;按照名为2的指针,查看您最终的位置,并将值+---------+ +---------+---------+ | addr X | ---> | 2 | 2 | +---------+ +---------+---------+ pointer a ^ in main | | +---------+ | | addr X |-----------+ +---------+ pointer a in change 放在那里。这意味着我们看到以下内容:

a[1] = 3

编写a也意味着&#34;按照名为1的指针,转到您找到的索引3处的元素,并将其替换为+---------+ +---------+---------+ | addr X | ---> | 2 | 3 | +---------+ +---------+---------+ pointer a ^ in main | | +---------+ | | addr X |-----------+ +---------+ pointer a in change 。这给出了以下内容:

change

现在,在main返回后,我们又回到amain中的+---------+ +---------+---------+ | addr X | ---> | 2 | 3 | +---------+ +---------+---------+ pointer a in main 指针未发生变化 - 它仍然在寻找与之前相同的位置 - 但它所指向的数组的值已更改

Invalid author specified. Example: A U Thor <author@example.com>

总结:

  • 指针在C中按值传递,这意味着如果将指针传递给函数,则会传递指针的副本。
  • 因此,如果将指针作为参数的函数更改指针指向的 ,那么它将在调用函数中无效。
  • 但是,如果某个功能更改指向的内容,则会反映在来电者中。

答案 1 :(得分:1)

inc 更改传递给它的指针的值 - 但传递给它的是原始指针值的副本,因此原始的仍然存在不变。

change不会改变指针本身,它会改变指针所指向的内容。

如果您希望inc更改原始指针,您必须将其更改为返回递增指针的函数,然后您将指定给原始指针:< / p>

int* inc(int* ip) {
  return ++ip;
}

然后在main

a = inc(a);

或者您可以重写inc以将指针指针作为参数,然后将原始指针的地址传递给它,如:

void inc(int** ipp) {
  *ipp = *ipp + 1;
}

然后从main将其称为:

inc(&a);

祝你好运。

答案 2 :(得分:0)

void inc(int* a) {
    a++;

此处a按值传递,因此在a内更改inc()不会反映在外部。

void change(int* a) {
    a[0] = 2;
    a[1] = 3;

此处a也按值传递,但您可以使用a更改a指向的内容a[0]a[1]

答案 3 :(得分:0)

a++会增加局部变量a的值。也就是说,踩到内存中的下一个位置。如果你想增加它,你应该使用(*a)++

符号a[1]只是隐藏指针算术的语法糖。这真正意味着*(a + 1)。这有一个有趣的副作用。 a[1]1[a]

相同

答案 4 :(得分:0)

对于inc函数,它正在更改参数a。由于C中的所有函数参数都是按值传递的,因此此更改不会反映在调用函数中。

调用change时,会执行以下操作:

a[0] = 2;
a[1] = 3;

与此相同:

*(a + 0) = 2;
*(a + 1) = 3;

具体来说,指针a正在解除引用。该函数不会更改a,而是a指向的内容。这就是为什么变化在函数之外可见。

答案 5 :(得分:0)

inc

中的代码
void inc(int* a) {
    a++;
}

更改指针值的副本,不会影响传递的参数。要影响参数,请通过引用而不是值传递它:

void inc(int*& a) {
    a++;
}