C语言中结构体和指针的malloc [英] malloc for struct and pointer in C

查看:74
本文介绍了C语言中结构体和指针的malloc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想定义一个表示向量长度及其值的结构:

Suppose I want to define a structure representing length of the vector and its values as:

struct Vector{
    double* x;
    int n;
};

现在,假设我想定义一个向量 y 并为其分配内存.

Now, suppose I want to define a vector y and allocate memory for it.

struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));

我在互联网上的搜索表明我应该为 x 单独分配内存.

My search over the internet show that I should allocate the memory for x separately.

y->x = (double*)malloc(10*sizeof(double));

但是,似乎我为 y->x 分配了两次内存,一次为 y 分配内存,另一次为 y->x 分配内存,这似乎很浪费内存.如果让我知道编译器真正做了什么以及什么是正确的方法,我将不胜感激初始化 y 和 y->x.

But, it seems that I am allocating the memory for y->x twice, one while allocating memory for y and the other while allocating memory for y->x, and it seems a waste of memory. It is very much appreciated if let me know what compiler really do and what would be the right way to initialize both y, and y->x.

提前致谢.

推荐答案

不,您不是y->x 分配内存两次.

No, you're not allocating memory for y->x twice.

相反,您正在为结构(包括一个指针)分配内存加上该指针指向的一些东西.

Instead, you're allocating memory for the structure (which includes a pointer) plus something for that pointer to point to.

这样想:

         1          2
        +-----+    +------+
y------>|  x------>|  *x  |
        |  n  |    +------+
        +-----+

因此您实际上需要两个分配(12)来存储所有内容.

So you actually need the two allocations (1 and 2) to store everything.

另外,你的类型应该是 struct Vector *y 因为它是一个指针,你不应该在 C 中转换 malloc 的返回值,因为它可以隐藏某些问题你不想隐藏 - C 完全有能力将 void* 返回值隐式转换为任何其他指针.

Additionally, your type should be struct Vector *y since it's a pointer, and you should never cast the return value from malloc in C since it can hide certain problems you don't want hidden - C is perfectly capable of implicitly converting the void* return value to any other pointer.

而且,当然,您可能希望封装这些向量的创建,以便更轻松地管理它们,例如:

And, of course, you probably want to encapsulate the creation of these vectors to make management of them easier, such as with:

struct Vector {
    double *data;    // no place for x and n in readable code :-)
    size_t size;
};

struct Vector *newVector (size_t sz) {
    // Try to allocate vector structure.

    struct Vector *retVal = malloc (sizeof (struct Vector));
    if (retVal == NULL)
        return NULL;

    // Try to allocate vector data, free structure if fail.

    retVal->data = malloc (sz * sizeof (double));
    if (retVal->data == NULL) {
        free (retVal);
        return NULL;
    }

    // Set size and return.

    retVal->size = sz;
    return retVal;
}

void delVector (struct Vector *vector) {
    // Can safely assume vector is NULL or fully built.

    if (vector != NULL) {
        free (vector->data);
        free (vector);
    }
}

通过像这样封装创建,您可以确保向量要么完全构建,要么根本没有构建——它们不可能是半构建的.它还允许您将来在不影响客户端的情况下完全更改底层数据结构(例如,如果您想让它们成为稀疏数组以牺牲空间换取速度).

By encapsulating the creation like that, you ensure that vectors are either fully built or not built at all - there's no chance of them being half-built. It also allows you to totally change the underlying data structures in future without affecting clients (for example, if you wanted to make them sparse arrays to trade off space for speed).

这篇关于C语言中结构体和指针的malloc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆