我希望有人可以帮我弄清楚为什么以下代码的一个版本有效,而另一个版本没有。下面我已经包含 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;
}
答案 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()
函数中取消引用此空指针时,会出现未定义的行为。