【发布时间】:2018-05-24 16:40:34
【问题描述】:
我对 C 中的动态内存分配有疑问。 我目前正在研究 C 中的人工神经网络实现。 我发现了一个名为 genann 的现有项目,在那里我注意到了一种我不熟悉的内存分配方法。
考虑一个结构:
typedef struct
{
int an, bn;
double *a, *b
} foo;
还有一个初始化函数:
foo *foo_init(int an, int bn)
{
foo *f;
f = malloc(sizeof(*f));
f->an = an;
f->bn = bn;
f->a = malloc(an*sizeof(*f->a));
f->b = malloc(bn*sizeof(*f->b));
return f;
}
这里有一个不同的 init 函数,就像在提到的项目中一样:
foo *foo_init(int an, int bn)
{
foo *f;
f = malloc(sizeof(*f) + an*sizeof(*f->a) + bn*sizeof(*f->b));
f->an = an;
f->bn = bn;
f->a = (double*)((char*)f + sizeof(*f)); // Could be f->a = (double*)(f + 1); ?
f->b = f->a + an;
return f;
}
所以在想这两种方法有什么区别。我能想到的第二种方法的唯一优点是我只需要分配和释放一个内存块,但由于它只是一个可能只调用一次的 init 函数,因此性能差异应该是微不足道的。另一方面,不同类型的指针指向同一个内存块,但我认为这并不违反严格的别名规则,因为它们指向块内的不同内存(?)。调整大小可能很困难,因为它不能像第一个 init 函数那样使用简单的 realloc 来完成。例如,如果我想将 a 和 b 缩小 1 并重新分配整个内存块,则最后两个 b 值会丢失(而不是一个 a,一个 b)。
我的结论是,以第一种方式分配内存更好,因为第二种方式几乎只有缺点。 init 函数之一是不好的做法吗?我错过了什么,这会使第二个功能更好吗?也许他们在项目中使用第二个是有特殊原因的?
提前致谢。
【问题讨论】:
-
@achal 我不这么认为。
-
@achal: 不应该是
*(f->a),但由于->绑定更强,我不需要括号。
标签: c dynamic-memory-allocation