在C中通过地址与指针将结构传递到函数

在C中通过地址与指针将结构传递到函数,c,pointers,struct,C,Pointers,Struct,我希望有人能帮我弄明白为什么下面代码的一个版本可以工作,而另一个版本不行。下面我介绍了存储在“worksheet.c”中的initArray方法。该函数在main中访问,下面给出了两个版本 void initArray(struct dynArray *a) { a->data = malloc(10 * TYPE_SIZE); assert(a->data != 0); a->size = 0; a->capacity = 10;

我希望有人能帮我弄明白为什么下面代码的一个版本可以工作,而另一个版本不行。下面我介绍了存储在“worksheet.c”中的initArray方法。该函数在main中访问,下面给出了两个版本

void initArray(struct dynArray *a) {
    a->data = malloc(10 * TYPE_SIZE);
    assert(a->data != 0);
    a->size = 0;
    a->capacity = 10;   
}
这很有效。我创建了一个dynArray结构,并通过引用将其传递给initArray

#include "worksheet0.h"
#include <stdio.h>

int main(void)
{
    struct dynArray b;
    initArray(&b);
    return 0;
}
int main(void)
{
    struct dynArray *b = NULL;
    initArray(b);
    return 0;
}

因为在第二种情况下,没有分配结构指针指向的内存。它只是一个具有值
NULL
的指针。在您的案例中,通过取消引用值
NULL
调用了未定义的行为

如果您分配内存,对其进行更改,然后返回它的值,它就会工作。[但您必须返回分配内存的地址。]您可以传递指针变量的地址,并分配取消引用的指针(此处指针的类型为
struct dynAray**
)将指向的内存,并对其进行更改。 让我们慢慢地说清楚:

为什么第一个案例有效?您有一个
struct dynArray
变量,该变量的地址已传递到函数中,然后您访问了该地址的内容-等等!这意味着您已经访问了
struct dynArray
变量本身,并对其成员变量进行了更改。是的,第一个案例就是这样的

在第二种情况下,您有一个指向
struct dynArray
的指针。然后你传递了它-取消引用了它。它指的是哪里?它包含的是某个
struct dynArray
变量的地址吗?没有。它是
NULL
。因此,如果你期望它能起作用,那就错了

第二种方法可行,但你必须改变一些事情!让我们看看如何:

struct dynArray* initArray() {
    struct dynArray* a = malloc(sizeof *a);
    assert(a != NULL);
    a->data = malloc(10 * TYPE_SIZE);
    assert(a->data != 0);
    a->size = 0;
    a->capacity = 10;
    return a;   
}
main()中

您甚至不需要传递指针变量。如果你想这样做,那就没有意义了

您知道,您还可以传递指针变量的地址,以便对其进行更改-

void initArray(struct dynArray** a) {
    *a = malloc(sizeof **a);
    assert((*a) != NULL);
    (*a)->data = malloc(10 * TYPE_SIZE);
    assert((*a)->data != 0);
    (*a)->size = 0;
    (*a)->capacity = 10;  
}
对于
main()
中的这个,您可以这样调用它

struct dynArray* b;
initArray(&b);

因为在第二种情况下,没有分配结构指针指向的内存。它只是一个具有值
NULL
的指针。在您的案例中,通过取消引用值
NULL
调用了未定义的行为

如果您分配内存,对其进行更改,然后返回它的值,它就会工作。[但您必须返回分配内存的地址。]您可以传递指针变量的地址,并分配取消引用的指针(此处指针的类型为
struct dynAray**
)将指向的内存,并对其进行更改。 让我们慢慢地说清楚:

为什么第一个案例有效?您有一个
struct dynArray
变量,该变量的地址已传递到函数中,然后您访问了该地址的内容-等等!这意味着您已经访问了
struct dynArray
变量本身,并对其成员变量进行了更改。是的,第一个案例就是这样的

在第二种情况下,您有一个指向
struct dynArray
的指针。然后你传递了它-取消引用了它。它指的是哪里?它包含的是某个
struct dynArray
变量的地址吗?没有。它是
NULL
。因此,如果你期望它能起作用,那就错了

第二种方法可行,但你必须改变一些事情!让我们看看如何:

struct dynArray* initArray() {
    struct dynArray* a = malloc(sizeof *a);
    assert(a != NULL);
    a->data = malloc(10 * TYPE_SIZE);
    assert(a->data != 0);
    a->size = 0;
    a->capacity = 10;
    return a;   
}
main()中

您甚至不需要传递指针变量。如果你想这样做,那就没有意义了

您知道,您还可以传递指针变量的地址,以便对其进行更改-

void initArray(struct dynArray** a) {
    *a = malloc(sizeof **a);
    assert((*a) != NULL);
    (*a)->data = malloc(10 * TYPE_SIZE);
    assert((*a)->data != 0);
    (*a)->size = 0;
    (*a)->capacity = 10;  
}
对于
main()
中的这个,您可以这样调用它

struct dynArray* b;
initArray(&b);

在第一个示例中,将保存实际
struct
地址的指针传递给函数。但是,在第二个示例中,指针
b
不指向
struct
。相反,此指针被初始化为
NULL
,当此空指针在
initArray()
函数中被取消引用时,会出现未定义的行为。

在第一个示例中,将保存实际
结构的地址的指针传递给函数。但是,在第二个示例中,指针
b
不指向
struct
。相反,此指针初始化为
NULL
,当此空指针在
initArray()
函数中被取消引用时,会出现未定义的行为。

将值
NULL
传递给
void initArray(struct dynArray*a)
然后
a->data
derefrences
NULL
;c->size=0NULL
传递给
void initArray(struct dynArray*a)
时,然后
a->data
derefrences
NULL
。如果您编写了
struct dynArray*c=NULL;c->size=0