malloc表示C中的结构和指针

时间:2022-06-01 21:37:12

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

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

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

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

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

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

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

我在因特网上的搜索表明我应该分别为x分配内存。

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

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分配内存两次,一次为y分配内存,另一次为y->x分配内存,这似乎是在浪费内存。如果让我知道编译器的真正功能以及初始化y和y->x的正确方法,我将非常感激。

Thanks in advance.

提前谢谢。

7 个解决方案

#1


104  

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

不,你没有为y->x分配两次内存。

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

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

Think of it this way:

这样想:

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

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

所以你实际上需要两个分配(1和2)来存储所有东西。

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.

此外,您的类型应该是struct Vector *y,因为它是一个指针,而且您不应该在C中使用malloc来强制转换返回值,因为它可以隐藏某些您不希望隐藏的问题——C完全能够隐式地将void*返回值转换为任何其他指针。

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

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

#2


4  

The first time around, you allocate memory for Vector, which means the variables x,n.

第一次,你为向量分配内存,也就是变量x n。

However x doesn't yet point to anything useful.

然而x还没有指出任何有用的东西。

So that is why second allocation is needed as well.

这就是为什么第二种分配也是必须的。

#3


3  

Few points

几个点

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

结构向量y = (struct Vector*)malloc(sizeof(struct Vector));是错误的

it should be struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector)); since y holds pointer to struct Vector.

它应该是struct Vector* y = (struct Vector*)malloc(sizeof(struct Vector));因为y是指向结构向量的指针。

1st malloc() only allocates memory enough to hold Vector structure (which is pointer to double + int)

第1个malloc()仅分配足够的内存来保存向量结构(它是指向双+ int的指针)

2nd malloc() actually allocate memory to hold 10 double.

第二个malloc()实际上分配内存以容纳10倍。

#4


1  

In principle you're doing it correct already. For what you want you do need two malloc()s.

原则上你已经做对了。您需要两个malloc()s。

Just some comments:

只是一些评论:

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

should be

应该是

struct Vector *y = malloc(sizeof *y); /* Note the pointer */
y->x = calloc(10, sizeof *y->x);

In the first line, you allocate memory for a Vector object. malloc() returns a pointer to the allocated memory, so y must be a Vector pointer. In the second line you allocate memory for an array of 10 doubles.

在第一行,为向量对象分配内存。malloc()返回一个指向已分配内存的指针,因此y必须是一个向量指针。在第二行中,为一个10倍的数组分配内存。

In C you don't need the explicit casts, and writing sizeof *y instead of sizeof(struct Vector) is better for type safety, and besides, it saves on typing.

在C语言中,您不需要显式强制类型转换,而使用sizeof *y而不是sizeof(struct Vector)更有利于类型安全,此外,还可以节省输入。

You can rearrange your struct and do a single malloc() like so:

您可以重新安排您的结构并执行一个malloc(),如下所示:

struct Vector{    
    int n;
    double x[];
};
struct Vector *y = malloc(sizeof *y + 10 * sizeof(double));

#5


0  

When you allocate memory for struct Vector you just allocate memory for pointer x, i.e. for space, where its value, which contains address, will be placed. So such way you do not allocate memory for the block, on which y.x will reference.

当你为struct Vector分配内存时,你只是为指针x分配内存,也就是空间,它的值,包含地址,会被放置在空间中。这样你就不会为block分配内存,在这个y上。x将参考。

#6


0  

First malloc allocates memory for struct, including memory for x (pointer to double). Second malloc allocates memory for double value wtich x points to.

首先,malloc为struct分配内存,包括x的内存(指向double的指针)。第二个malloc为wtich x指向的双值分配内存。

#7


0  

You could actually do this in a single malloc by allocating for the Vector and the array at the same time. Eg:

实际上,你可以在一个malloc中通过同时分配向量和数组来实现这一点。例如:

struct Vector y = (struct Vector*)malloc(sizeof(struct Vector) + 10*sizeof(double));
y->x = (double*)((char*)y + sizeof(struct Vector));
y->n = 10;

This allocates Vector 'y', then makes y->x point to the extra allocated data immediate after the Vector struct (but in the same memory block).

这将分配向量“y”,然后使y->x指向向量结构之后立即分配的额外数据(但在相同的内存块中)。

If resizing the vector is required, you should do it with the two allocations as recommended. The internal y->x array would then be able to be resized while keeping the vector struct 'y' intact.

如果需要调整向量的大小,您应该按照建议对这两个分配进行调整。然后,内部的y->x数组将能够调整大小,同时保持向量结构'y'不变。

#1


104  

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

不,你没有为y->x分配两次内存。

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

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

Think of it this way:

这样想:

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

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

所以你实际上需要两个分配(1和2)来存储所有东西。

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.

此外,您的类型应该是struct Vector *y,因为它是一个指针,而且您不应该在C中使用malloc来强制转换返回值,因为它可以隐藏某些您不希望隐藏的问题——C完全能够隐式地将void*返回值转换为任何其他指针。

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

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

#2


4  

The first time around, you allocate memory for Vector, which means the variables x,n.

第一次,你为向量分配内存,也就是变量x n。

However x doesn't yet point to anything useful.

然而x还没有指出任何有用的东西。

So that is why second allocation is needed as well.

这就是为什么第二种分配也是必须的。

#3


3  

Few points

几个点

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

结构向量y = (struct Vector*)malloc(sizeof(struct Vector));是错误的

it should be struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector)); since y holds pointer to struct Vector.

它应该是struct Vector* y = (struct Vector*)malloc(sizeof(struct Vector));因为y是指向结构向量的指针。

1st malloc() only allocates memory enough to hold Vector structure (which is pointer to double + int)

第1个malloc()仅分配足够的内存来保存向量结构(它是指向双+ int的指针)

2nd malloc() actually allocate memory to hold 10 double.

第二个malloc()实际上分配内存以容纳10倍。

#4


1  

In principle you're doing it correct already. For what you want you do need two malloc()s.

原则上你已经做对了。您需要两个malloc()s。

Just some comments:

只是一些评论:

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

should be

应该是

struct Vector *y = malloc(sizeof *y); /* Note the pointer */
y->x = calloc(10, sizeof *y->x);

In the first line, you allocate memory for a Vector object. malloc() returns a pointer to the allocated memory, so y must be a Vector pointer. In the second line you allocate memory for an array of 10 doubles.

在第一行,为向量对象分配内存。malloc()返回一个指向已分配内存的指针,因此y必须是一个向量指针。在第二行中,为一个10倍的数组分配内存。

In C you don't need the explicit casts, and writing sizeof *y instead of sizeof(struct Vector) is better for type safety, and besides, it saves on typing.

在C语言中,您不需要显式强制类型转换,而使用sizeof *y而不是sizeof(struct Vector)更有利于类型安全,此外,还可以节省输入。

You can rearrange your struct and do a single malloc() like so:

您可以重新安排您的结构并执行一个malloc(),如下所示:

struct Vector{    
    int n;
    double x[];
};
struct Vector *y = malloc(sizeof *y + 10 * sizeof(double));

#5


0  

When you allocate memory for struct Vector you just allocate memory for pointer x, i.e. for space, where its value, which contains address, will be placed. So such way you do not allocate memory for the block, on which y.x will reference.

当你为struct Vector分配内存时,你只是为指针x分配内存,也就是空间,它的值,包含地址,会被放置在空间中。这样你就不会为block分配内存,在这个y上。x将参考。

#6


0  

First malloc allocates memory for struct, including memory for x (pointer to double). Second malloc allocates memory for double value wtich x points to.

首先,malloc为struct分配内存,包括x的内存(指向double的指针)。第二个malloc为wtich x指向的双值分配内存。

#7


0  

You could actually do this in a single malloc by allocating for the Vector and the array at the same time. Eg:

实际上,你可以在一个malloc中通过同时分配向量和数组来实现这一点。例如:

struct Vector y = (struct Vector*)malloc(sizeof(struct Vector) + 10*sizeof(double));
y->x = (double*)((char*)y + sizeof(struct Vector));
y->n = 10;

This allocates Vector 'y', then makes y->x point to the extra allocated data immediate after the Vector struct (but in the same memory block).

这将分配向量“y”,然后使y->x指向向量结构之后立即分配的额外数据(但在相同的内存块中)。

If resizing the vector is required, you should do it with the two allocations as recommended. The internal y->x array would then be able to be resized while keeping the vector struct 'y' intact.

如果需要调整向量的大小,您应该按照建议对这两个分配进行调整。然后,内部的y->x数组将能够调整大小,同时保持向量结构'y'不变。