我有一个包含动态分配数组的结构。
我已经写了下面的代码,它工作,但我不明白为什么它确实工作。
#include <stdio.h>
#include <stdlib.h>
struct Tray {
int *parr;
};
int allocateTray(int n, struct Tray *tray) {
tray->parr = calloc(n, sizeof(*tray->parr));
for (int i = 0; i<n; i++) {
tray->parr[i] = i+1;
}
}
int main() {
struct Tray tray = {NULL}, *ptray;
int n;
n = 5;
ptray = &tray;
allocateTray(n, ptray);
for (int i = 0; i<n; i++) {
printf("ptray->parr[%d] = %d \n", i, ptray->parr[i]);
}
return 0;
}
对于数组(不在结构体中),即使我在带参数int *arr
的函数中分配arr
,它也不会给予main
分配的数组,而是强制main
在那里使用双指针。
但是在这个例子中,我只是使用了一个指向结构体的指针,它工作了,我在想我应该使用一些类似双指针的东西来指向结构体。
为什么在这种情况下,它只与一个指针?
4条答案
按热度按时间oug3syen1#
一般来说,无论函数通过参数列表传递时要修改的对象是什么,都需要传递对象的 * address *,而不是对象本身。
对于
T s
,如果要修改s
,则函数原型的参数应为;void func(T *s);
调用示例为
对于
T *s
,如果要修改*s
,则函数原型的参数应为;void func(T **s);
调用示例为
对于
T **s
,如果要修改**s
,则函数原型的参数应为;void func(T ***s);
调用示例为
等等......(注意每一个的调用约定的明显相似性。)
示例-以下代码将无法更改其参数值:
但是这个例子传递地址并且能够改变值:
是的,作为函数原型中的一个参数,当需要更改指针对象所指向的内存内容时,它将起作用。
对于需要在函数中修改的指针(指向任何对象),情况也是如此,必须传递它的 * address *,而不是指针本身。这就需要该函数的参数容纳指向指针的指针。下面是一个简单的例子,使用
struct
、int
成员以及int *
成员:t98cgbkg2#
你不需要"双指针";你需要一个指向你要修改的对象的指针。2如果你想让函数修改一个指针对象,你需要传递一个指向那个对象的指针。3如果你想让函数修改一个结构,你需要传递一个指向那个对象的指针。
这正是你的代码所做的,你想修改
main
的tray
,所以你传递一个指针到main
的tray
,所以你的代码可以工作。下面的例子说明了这一点。
首先,让我们看一下不起作用的代码。
这段代码修改了
ac
,但没有修改a
。它没有达到我们想要的效果。要修改a
,我们需要传递a
的地址。这里,我们没有修改参数,而是将
*ap
修改为a
。这段代码确实实现了我们希望它实现的目标。现在,让我们介绍一下结构体。
这段代码修改了
sc
,但没有修改s
。它没有达到我们想要的效果。要修改s
,我们需要传递s
的地址。在这里,我们没有修改参数,而是将
*sp
修改为s
。这段代码确实实现了我们希望它实现的目标。Full demo:
警告:
输出:
mznpcxlj3#
要更改函数中的对象,需要通过引用传递,而不是通过值传递。
在C语言中,通过引用传递意味着通过一个指向对象的指针间接传递对象。因此,通过解引用传递的指针,你将直接访问指针所指向的对象,并可以更改它。
对于一个数组(不在结构体中),即使我在一个参数为int *arr的函数中分配arr,它也不会给予main分配的数组,而是强制main在那里使用双指针。
这意味着指针是按值传递给函数的。也就是说,函数处理由传递的指针的值初始化的局部变量(参数)。更改局部变量不会更改用作函数参数的原始指针。
考虑一个简单的程序
您可以按照以下方式来想象函数定义及其调用
正如你所看到的,函数改变了它的局部变量
p
,这个变量是由传递给函数的指针a
的值初始化的,而原来的指针a
保持不变。如果你想改变函数main中声明的指针
a
,你需要通过引用传递它,也就是说,程序看起来像下面这样现在在函数中取消引用指针
p
你可以直接访问原始指针
a
,从而可以改变它。对于你的第一个程序,在结构
Tray
中声明的指针parr
通过指向结构类型的对象的指针以引用方式传递给函数。
也就是说,在函数中取消引用指针
ptray
,您可以直接访问结构类型的原始对象,并可以更改(任何)其数据成员。uklbhaso4#
Gerhardh的评论是正确的:您*****正在使用双指针。
考虑: