malloc在C中的结构和指针
假设我想定义一个表示向量长度和它的值的结构:
struct Vector{ double* x; int n; };
现在,假设我想定义一个向量y并为其分配内存。
struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
我在互联网上的search显示,我应该分开分配x的内存。
y->x = (double*)malloc(10*sizeof(double));
但是,似乎我为y-> x分配了两次内存,一次为y分配内存,另一次为y-> x分配内存,这似乎是内存浪费。 非常感谢,让我知道什么编译器真的做什么和什么是正确的方式来初始化y和y-> x。
提前致谢。
不,你不会为y->x
分配两次内存。
相反,你正在为结构(包括一个指针) 加上一些指针指向的内存。
这样想:
1 2 +-----+ +------+ y------>| x------>| *x | | n | +------+ +-----+
所以你实际上需要两个分配( 1
和2
)来存储所有的东西。
另外,你的types应该是struct Vector *y
因为它是一个指针,并且你不应该在C中使用malloc
返回值,因为它可以隐藏你不想隐藏的某些问题 – C完全能够隐式地将void*
将值返回给任何其他指针。
当然,您可能想要封装这些向量的创build,使其更易于pipe理,例如:
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); } }
通过封装这样的创作,你可以确保vector或者完全构build或者根本不构build – 他们没有半机会的机会。 它还允许您在未影响客户端的情况下完全更改基础数据结构(例如,如果您想使它们成为稀疏arrays以换取空间来换取速度)。
第一次,你为Vector
分配内存,这意味着variablesx
, n
。
但是, x
还没有指向任何有用的东西 。
所以这就是为什么第二次分配也是需要的 。
几点
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector));
是错的
它应该是struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
因为y
持有指向struct Vector
指针。
第一个malloc()
只分配足够的内存来保存向量结构(这是指向double + int)
第二个malloc()
实际分配内存10倍。
原则上你已经做得正确了。 对于你想要的,你需要两个malloc()
。
只是一些评论:
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector)); y->x = (double*)malloc(10*sizeof(double));
应该
struct Vector *y = malloc(sizeof *y); /* Note the pointer */ y->x = calloc(10, sizeof *y->x);
在第一行中,为Vector对象分配内存。 malloc()
返回一个指向分配内存的指针,所以y必须是一个Vector指针。 在第二行中,为10个双精度数组分配内存。
在C中,你不需要显式的强制转换,而写sizeof *y
而不是sizeof(struct Vector)
对于types安全来说是更好的,而且还可以节省input的时间。
你可以重新排列你的结构,并像这样做一个malloc()
:
struct Vector{ int n; double x[]; }; struct Vector *y = malloc(sizeof *y + 10 * sizeof(double));
当你为struct Vector
分配内存的时候,你只需要为指针x
分配内存,也就是空间,其中包含地址的值将被放置。 所以这样的方式,你不会分配的内存块, yx
将参考。
第一个malloc为struct分配内存,包括x的内存(指向double的内存)。 第二个malloc为double值wtich x指向内存分配。
实际上,你可以在一个malloc中同时分配Vector和数组。 例如:
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector) + 10*sizeof(double)); y->x = (double*)((char*)y + sizeof(struct Vector)); y->n = 10;
这将分配Vector'y',然后使y-> x指向Vector结构之后(但是在同一个内存块中)的额外分配数据。
如果需要调整向量的大小,则应该按照build议的那样使用两个分配。 内部y-> x数组可以在保持向量结构“y”完整的情况下被resize。