繁体   English   中英

通过函数初始化C结构

[英]Initialize C struct through a function

所以我必须在C中编写一个类似vector的数据结构。通常我做了这样的结构:

struct Vector
{
    int length;
    int *elements;
};

和这些功能:

void initialize_vector(struct Vector* vector);
void create_vector(struct Vector* vector, int* array, int n);
void remove_vector(struct Vector* vector);
void vector_add_element(struct Vector* vector, int element);
void vector_insert(struct Vector* vector, int index, int element);
void vector_remove_element(struct Vector* vector, int element);
void vector_remove_at(struct Vector* vector, int index);

现在,在initialize_vector()函数中,我希望它只是将矢量属性初始化为默认值(例如, length为0, *elements为NULL)。 我写了这样的东西:

void initialize_vector(struct Vector* vector)
{
    vector->elements = NULL;
    vector->length = 0;
}

我试着检查它是否有效,所以我写了这段代码:

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


int main(int arc, char** argv)
{
    struct Vector* vec;
    initialize_vector(vec);
    printf("%d\n", vec->length);
    return 0;
}

我得到了着名的Segmentation fault ,所以我检查了GDB,当然一切都搞砸了这一行: vector->elements = NULL;

我不知道问题出在哪里。 我宣布一个向量,我猜它正确传递它并且它混乱了。 我知道这可能是微不足道的,我会被一些超级计划的家伙大肆投票,但是,嘿,他没有任何疑问,没有任何学问。

你没有声明一个向量,你声明了一个指向向量的指针 该指针未初始化,因此尝试取消引用它会调用未定义的行为

创建一个struct Vector并传递其地址:

struct Vector vec;
initialize_vector(&vec);
printf("%d\n", vec.length);

如果要同时为struct Vector分配空间,请更改函数以调用malloc并返回指针:

struct Vector *initialize_vector()
{
    struct Vector *vector = malloc(sizeof(*vector));
    if (!vector) {
        perror("malloc failed");
        exit(1);
    }
    vector->elements = NULL;
    vector->length = 0;
    return vector;
}

...

struct Vector *vector = initialize_vector();

dbush给出了一个很好的答案,所以我不会给你代码。 相反,我会给出一个小C指针解释,这样你就不会再遇到同样的错误。

struct Vector * vec;

声明指向结构的指针,而不是实际的结构。 什么是指针? 它是一个包含地址的变量。 因此,所有指针,无论它们是int *,char *,char **还是struct Vector *,都具有相同的大小(通常为32位或64位,具体取决于体系结构)。 声明指针类型仅对取消引用指针(获取存储在该内存地址中的数据)非常有用。 因此,取消引用void *指针会导致错误。 回到上面的语句,用英语,这个声明写道:“vec是一个可以保存struct Vector地址的变量。” 但此时,vec没有有效地址。

在为指针变量赋值之前,存储在该变量中的地址是垃圾,我们称之为未初始化的变量。 在您的情况下,您将此未初始化的地址传递给initialize_vector(),该地址尝试访问存储在该地址中的值。 但正如我们所知,这个地址是垃圾。 这给了seg错误。

另一点需要指出的是,在编写这些函数时,您需要做出设计决策。 你想让struct Vectors生活在堆上(通过调用malloc)还是堆栈? 堆允许更大的灵活性,但它还要求程序员仔细跟踪正在使用的指针以避免内存泄漏,这可能会变得棘手。 如果我是你,我会从堆栈中的对象开始,然后将它们的地址传递给修改函数。 dbush的第一个答案。 这样您就不必担心调用free()了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM