1

Numerical recipes, 2nd edition ( http://numerical.recipes ) 一书使用以下代码为带有下标 [nl..nh] 的向量 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));
}

问题1:加/减NR_END元素的目的是什么?

问题2:转换float *char *in的目的是什么free_vector

我知道这+1malloc由于数组的包含右边界(通常在 C 中不包含)。

4

1 回答 1

1
  1. 假设你有nl=1NR_END=0。然后返回的指针将越界(它指向分配的块之前)。这是未定义的行为,可能导致不正确的结果,尽管它不太可能在主要编译器上引起问题,因为指针会在取消引用之前递增。

    为了避免这种未定义的行为,您可以设置NR_END为最大期望值nl(本书中为 1)。这保证了返回的指针是有效的。但是,问题中给出的实现仍然不正确,因为在递增之前v-nl+NR_END递减。正确的实现是.nlNR_ENDv+NR_END-nl

    请注意,如果nl只有非负值,更简单的实现将是简单地分配nh+1值,然后您不需要任何指针算术 aftermalloc或 before free

    在这里,您可以从第二版的第 940-941 页中看到解释这一点的书中的引述。一些报价:

    在极少数情况下(并且可能仅在分段机器上)可能会发生表达式 b-1 根本没有表示的情况。如果发生这种情况,则不能保证满足关系 b=(b-1)+1。

    [……]

    参数 NR_END 用作在每个向量或矩阵块的开头分配的多个额外存储位置,只是为了使偏移指针引用保证可表示。

  2. 在 C 的任何标准化版本中都不需要强制转换char*。在古代版本中可能需要它。malloc也不需要转换返回值。

于 2018-11-19T17:09:40.450 回答