gpt4 book ai didi

c - 通过引用调用的行为

转载 作者:太空宇宙 更新时间:2023-11-04 05:19:40 25 4
gpt4 key购买 nike

在我的程序中,我是一个传递指向函数的指针。在该函数中,我将使传递的指针指向另一个指针所指向的位置。从函数返回时,它不再指向其新位置,而是指向其原始位置。由于我是通过引用调用传递的,所以它应该指向它的新位置。为什么会这样?

// a program to show behavior of call by reference

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

void ptrAllocation(int *p)
{
int k = 10 ;
int *t = &k;
p = t ;
printf("\np now points : %d",*p);
}

int main()
{
int i = 5 ;
int *a = &i;
ptrAllocation(a);
printf("\na now points : %d",*a);
}

输出:
p now points : 10
a now points : 5

我知道如果我做这样的函数,问题是可以解决的:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}

但我不能从指针、位置、堆栈的角度清楚地了解程序中到底发生了什么?
我的问题:
是指针是否指向函数中的指针,但当函数返回时,指针不存在,所以指针指向它原来的位置。
当给一个指针分配一个指针时,像in k一样,指针 tptrAllocation都指向同一个位置,而不是 t指向 pp = t指向该位置。
请描述堆栈和指针如何在上面的程序中工作。

最佳答案

您传递的是值,而不是引用。传递值的是指针,但指针仍按值传递。你可以改变它指向什么;你不能改变调用函数中的指针。如果你想这样做,你就必须传递一个指向指针的指针,就像在你的第二个代码片段中一样。
这是一个基于代码的派生程序,它的输出来自于一个64位的macosx10.8.3版本。我在地址打印中使用了12来在这台机器上给出统一宽度的指针输出;你可以调整它以适合你的机器。

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

static int q = 42;

static void ptrAllocation(int *p, int **z)
{
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
int k = 10;
int *t = &k;
*z = &q;
p = t;
printf("After:\n");
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
}

int main(void)
{
int i = 5;
int j = 7;
int *a = &i;
int *b = &j;
printf("Before:\n");
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
ptrAllocation(a, &b);
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
}

样本输出:
Before:
a now points at: 5 (0x7FFF59E1852C)
b now points at: 7 (0x7FFF59E18530)
p now points at: 5 (0x7FFF59E1852C)
z now points at: 7 (0x7FFF59E18530) (0x7FFF59E18538)
After:
p now points at: 10 (0x7FFF59E18534)
z now points at: 42 (0x000105DE8050) (0x7FFF59E18538)
a now points at: 5 (0x7FFF59E1852C)
b now points at: 42 (0x000105DE8050)

研究输出应该有助于你更好地理解正在发生的事情。如果需要,可以打印更多地址值。
请描述堆栈和指针如何在上面的程序中工作。
我将讨论我显示的程序,因为地址可供讨论。
变量 q位于地址0x000105DEE8050。在 main()内部,变量 i存储在内存位置0x7FFF59E1852C的堆栈上;变量 j存储在内存位置0x7FFF59E18530上。变量 a包含 i的地址; b包含 j的地址; b本身的地址是0x7FFF59E18538; a的地址不显示在输出中。
调用 ptrAllocation()时, a的值被推送到堆栈上, b的地址也被推送到堆栈上。它是一个实现细节,按顺序推送值。
ptrAllocation()中,变量 p包含 a函数中 main()值的副本。变量 z包含 b函数中 main()的地址。变量 k在堆栈上;变量 t包含 k的地址。
赋值 *z = &q;通过参数 qb的地址赋值给指针 z;它通过改变调用函数中 b的值来改变 b所指向的位置-这是唯一可能的,因为传递了 b的地址。
赋值改变了局部变量 p = t;(它包含 p中变量 a中的内容的副本),从而指向 main()所指向的内容,即 t。因此,“After”打印语句注意到 k指向值10。 p指向的值在 **z中,仍然是42; q*z的地址。
返回时, q代码中的 a不会更改,因为它的地址没有传递给 main(),但 ptrAllocation()会更改,因为它的地址传递给了 b,并且 ptrAllocation()修改了指针。
正如对问题的评论中所指出的,您对 ptrAllocation()的第二次实现也有缺陷:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}

调用此函数后,无法可靠地取消对传递给它的指针的引用,因为 ptrAllocation()指向的局部变量在 *p返回时不再有效。您可以通过将 ptrAllocation()设置为 k来解决此问题,或者通过安排 static int k = 10;指向在函数外部具有作用域的其他 *p值(在函数外部定义的变量或动态分配的变量):
void ptrAllocation(int **p)
{
static int k = 10;
int *t = &k;
*p = t ;
printf("p now points : %d\n", **p);
}

或:
void ptrAllocation(int **p)
{
*p = malloc(sizeof(*t));
if (*p != 0)
{
**p = 10;
printf("p now points : %d\n", **p);
}
}

请注意,顺便说一下,我留下的代码在每个 int语句的末尾都有新行。养成在输出行的末尾加新行的习惯。如果不知道,则不知道输出何时出现(因为它可能会一直保持到下一次生成换行符)。

关于c - 通过引用调用的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16783165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com