《数值食谱》第 2 版 ( http://numerical.recipes ) 使用以下代码为带有下标 [nl..nh] 的 vector v 分配/释放内存:
#define NR_END 1
#define FREE_ARG char*
float *vector(long nl, long nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
float *v;
v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
if (!v) nrerror("allocation failure in vector()");
return v-nl+NR_END;
}
void free_vector(float *v, long nl, long nh)
/* free a float vector allocated with vector() */
{
free((FREE_ARG) (v+nl-NR_END));
}
问题一:加减NR_END
元素的目的是什么?
问题2:将free_vector
中的float *
转换为char *
的目的是什么?
我理解 malloc
中的 +1
是由于数组的包含右边界(在 C 中通常是非包含的)。
最佳答案
假设您有
nl=1
和NR_END=0
。然后返回的指针将越界(它指向分配的 block 之前)。这是未定义的行为,可能会导致不正确的结果,尽管它不太可能在主要编译器上引起问题,因为指针会在取消引用之前递增回来。为避免这种未定义的行为,您可以将
NR_END
设置为nl
的最大期望值(书中为1)。这保证了返回的指针是有效的。但是,问题中给出的实现仍然不正确,因为v-nl+NR_END
在递增NR_END
之前递减了nl
。正确的实现应该是v+NR_END-nl
。请注意,如果
nl
仅具有非负值,则更简单的实现是简单地分配nh+1
值,然后您不需要malloc
之后或free
之前的任何指针运算。Here您可以在第二版的第 940-941 页中看到书中的引述来解释这一点。一些引述:
it might happen in rare cases (and probably only on a segmented machine) that the expression b-1 has no representation at all. If this occurs, then there is no guarantee that the relation b=(b-1)+1 is satisfied.
[....]
the parameter NR_END is used as a number of extra storage locations allocated at the beginning of every vector or matrix block, simply for the purpose of making offset pointer references guaranteed-representable.
在 C 的任何标准版本中都不需要转换为
char*
。在古代版本中可能需要。转换malloc
的返回值是also not needed .
关于c - 关于《数值食谱》一书的问题,第 2 版。 : allocation/deallocation of memory for vectors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53378855/