gpt4 book ai didi

c - C中结构和指针的malloc

转载 作者:太空狗 更新时间:2023-10-29 16:16:15 25 4
gpt4 key购买 nike

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

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

现在,假设我想定义一个 vector y 并为其分配内存。

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

我在互联网上搜索显示我应该为 x 单独分配内存。

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

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

最佳答案

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

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

这样想:

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

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

另外,你的类型应该是 struct Vector *y 因为它是一个指针,你不应该在 C 中从 malloc 转换返回值。

它可以隐藏某些您不想隐藏的问题,并且 C 完全能够将 void* 返回值隐式转换为任何其他指针。

当然,您可能希望封装这些 vector 的创建以便于管理它们,例如在头文件 vector.h 中包含以下内容:

struct Vector {
double *data; // Use readable names rather than x/n.
size_t size;
};

struct Vector *newVector(size_t sz);
void delVector(struct Vector *vector);
//void setVectorItem(struct Vector *vector, size_t idx, double val);
//double getVectorItem(struct Vector *vector, size_t idx);

然后,在 vector.c 中,您拥有管理 vector 的实际函数:

#include "vector.h"

// Atomically allocate a two-layer object. Either both layers
// are allocated or neither is, simplifying memory checking.

struct Vector *newVector(size_t sz) {
// First, the vector layer.

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

// Then data layer, freeing vector layer if fail.

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

// Here, both layers worked. Set size and return.

vector->size = sz;
return vector;
}

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

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

通过像这样封装 vector 管理,您可以确保 vector 要么完全构建,要么根本不构建——它们没有可能是半构建的。

它还允许您在未来完全更改底层数据结构而不影响客户端。例如:

  • 如果你想让它们成为稀疏数组以牺牲空间换取速度。
  • 如果您希望在更改时将数据保存到持久存储中。
  • 如果您希望确保所有 vector 元素都初始化为零。
  • 如果您想将 vector 大小与 vector 容量分开以提高效率(1)

您还可以根据需要添加更多功能,例如安全地设置或获取 vector 值(请参阅 header 中的注释代码)。

例如,您可以(作为一种选择)默默地忽略有效范围之外的设置值,并在获得这些值时返回零。或者您可以引发某些描述错误,或尝试在幕后自动扩展 vector (1)


在使用 vector 方面,一个简单的例子如下(非常基础)main.c

#include "vector.h"

#include <stdio.h>

int main(void) {
Vector myvec = newVector(42);
myvec.data[0] = 2.718281828459;
delVector(myvec);
}

(1) 可扩展载体的潜力值得进一步解释。

许多 vector 实现将容量与大小分开。前者是在需要重新分配之前可以使用多少元素,后者是实际 vector 大小(总是 <= 容量)。

扩展时,您通常希望以不经常扩展的方式扩展,因为这可能是一项昂贵的操作。例如,您可以比绝对必要的多添加 5%,这样在循环中不断添加一个元素,就不必为每个项目重新分配。

关于c - C中结构和指针的malloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14768230/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com