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

时间:2018-01-25 03:39:26

标签: c pointers struct

我希望有人可以帮我弄清楚为什么以下代码的一个版本有效,而另一个版本没有。下面我已经包含 initArray 方法,存储在" worksheet.c"中。该功能在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;
}

这失败了一个seg错误。我认为在这里传递b与通过引用传递结构相同。

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

2 个答案:

答案 0 :(得分:3)

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

如果您分配内存,对其进行更改然后返回它的值,它将起作用。 [但是你必须返回分配的内存的地址。] OR 你可以传递指针变量的地址并分配解除引用指针的内存(这里指针的类型为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()

struct dynArray* b;
b  = initArray();

你甚至不需要传递指针变量。如果你想这样做,这将毫无意义。

而且你知道你也可以传递指针变量的地址,以便你可以对其进行更改 -

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);

答案 1 :(得分:0)

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