【问题标题】:Pointers of pointer and pass by reference指针的指针和通过引用传递
【发布时间】:2017-12-30 20:35:33
【问题描述】:

我很难理解指针的工作原理。 我得到它的方式是,当我声明一个指向 int 的指针时,我创建了一个变量,该变量将包含一个地址(必须初始化才能对 int 进行操作)和一个 int 变量。从视觉上看,我会以这种方式表示(地址;int)。例如,如果我声明

int* number;

我将“number”作为地址变量,“*number”作为 int 变量。

同样,声明诸如 int** d 之类的东西应该意味着创建一个指向 (address;int) 的指针。那将是 [address;(address;int)]。

考虑到这一点,我试图通过使用外部函数 incrementer_3 以及所谓的按引用传递来修改 **d 的 int 值,但在运行时出现错误。所以,我想知道我错过了什么。

#include <stdio.h>

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

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

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

int main() {
    int b = 7;
    incrementer(&b);
    printf("%d\n", b);

    int* c = (int*)malloc(sizeof(int));
    *c = 4;
    incrementer_2(&c);
    printf("%d\n", *c);

    int** d = (int**)malloc(sizeof(int*));
    **d = 6;
    incrementer_3(&d);
    printf("%d\n", **d);

    system("pause");
}

仅供参考,当我增加 b 和 c 时,这部分工作正常。 另外,我还想知道是否可以使用函数“incrementer”而不是“incrementer_2”来修改 *c 的值。事实上,我只是在想我可以简单地从 main 编写

incrementer(&(*c));

或者,以更简单的方式

incrementer(c);

但它们都不能在运行时工作。

【问题讨论】:

  • **d = 6; - 这会调用未定义的行为。你还没有初始化*d
  • 为什么不简单地使用int *c = &amp;b;int **d = &amp;c;
  • 还要注意C没有“按引用传递”,只能通过指针和address-of操作符模拟
  • 最后,以你的方式和我的方式,做例如incrementer(c) 应该可以正常工作(如果在您当前的代码中,您已正确初始化 c)。
  • @Someprogrammerdude 关于“通过引用传递”:事实上,我只是使用了我在老师的幻灯片中找到的术语。

标签: c pass-by-reference pointer-to-pointer


【解决方案1】:

您需要记住,指针实际上不需要引用任何东西,即使它确实引用了某些东西,也不一定是有效的。跟踪这些事情是您作为程序员的工作。

按照惯例,无效的指针将被赋予值 0(这是 NULL 最终的值),但这只是惯例,在某些情况下可能会使用其他值。

所以,用“int* number;”您已经声明了一个指向 int 的指针,但是因为它没有被初始化,所以您完全不知道它包含什么值,此时取消引用它是未定义的行为 - 这意味着如果您尝试过,大多数情况可能发生这样做,虽然实际上它可能只会让你的程序崩溃。

问题:

int** d = (int**)malloc(sizeof(int*));
    **d = 6;

是当 d 被初始化时 *d 不是。你可以这样做:

*d = malloc(sizeof(int));

 *d = c;

但是 *d 需要先指向某个东西,然后才能使用 **d。

【讨论】:

  • 谢谢,思路很清晰,程序现在可以运行了。
【解决方案2】:
int b

b 是一个int。我们可以写b来参考。

b = 7;

这里我们给b分配一个号码。

int* c 

c 是一个应该指向int 的指针。我们可以通过写*c来引用int

c = (int*)malloc(sizeof(int));

我们找到了一块可以容纳int的内存,并制作了一个指向该块的指针,并将其分配给c。一切都很好。

*c = 4;

这里我们给*c分配一个号码。看? *c 的行为就像 b。但这仅仅是因为我们已经用一个有效的指针初始化了它!否则,*c = 4; 将无效。

int** d

d 是一个指针,应该指向 int* 类型的事物,我们可以写成 *d 来引用它。反过来,那个int* 应该指向一个int,我们可以通过写**d 来引用它。

d = (int**)malloc(sizeof(int*));

我们找到了一块可以容纳int*的内存,并创建了一个指向该块的指针,并将其分配给d。一切都很好。既然int*我们叫*d,它指的是什么?

什么都没有。为了将它指向某个东西,我们可以找到一块可以容纳int的内存,并创建一个指向该块的指针,并将其分配给我们的*d,就像我们之前所做的那样c。看? *d 的行为就像 c。为了使用*c,我们必须先用一个有效的指针初始化c。为了使用**d,我们需要先用一个有效的指针初始化*d

*d = (int*)malloc(sizeof(int));

【讨论】:

    【解决方案3】:

    问题是您为int* 分配内存,但您没有为int 分配任何内存或设置int 的指针。 应该是:

    int** d = (int**)malloc(sizeof(int*)); *d = (int*)malloc(sizeof(int)); **d=6;

    我得到它的方式是,当我声明一个指向 int 的指针时,我创建了一个包含地址的变量(必须初始化才能对 int 进行操作)和一个 int 变量。

    不,当您声明一个指针时,您会创建一个知道如何包含地址的变量。当您使用malloc() 时,您会分配内存。 malloc() 返回一个您可以分配给指针的地址。

    附: - incrementer(c) 应该可以正常工作

    【讨论】:

    • 谢谢,现在可以了。关于最后一点,我不正确的意思是,我假设声明指向 int 的指针意味着创建一个具有两个字段的变量,一个用于包含地址,另一个用于包含 int 值。这个猜测是真的吗?
    • 不客气。不,一个指针只包含一个值——一个地址。您可以使用* . -&gt; 之类的运算符来处理指针指向的内存地址中的值。
    猜你喜欢
    • 2014-05-06
    • 2014-07-27
    • 2023-03-03
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    • 2019-09-16
    • 2021-02-28
    相关资源
    最近更新 更多