指针alingment和长度存储阵列

时间:2016-04-19 12:57:42

标签: c arrays pointers memory-management

我找到了一个数组的以下实现,其长度存储在"内部"它。这是代码:

double* construct(const size_t nElements)
{
  double* arr = malloc(sizeof(double) * nElements + sizeof(int));
  int i = 0;

  *(int*)arr = nElements;
  ((int*)arr)++;

  for (i = 0; i < nElements; i++) arr[i] = 1.0 * i;      

  return arr;
}

void destroy(double* arr)
{
  free((int*)arr - 1);
}

void print(double* arr)
{
  int N = *((int*)arr - 1);
  int i = 0;

  printf("Supplied array of %d elements:\n", N);

  for (i = 0; i < N; i++) printf("%d : %f\n", i, arr[i]);      
}

int main(void)
{
  double* a = construct(10);

  print(a);    
  destroy(a);

  return 0;
}

这种技术背后的想法是分配一个带有额外空间的内存块来存储数组的长度,并为用户提供仅实际数据开始的指针。但是,我怀疑在这个特定的实现中,在指针转换方面有些可疑(从double 到int *)。

这一般是允许的吗?

如果是,它如何在指针对齐方面起作用?

有更好的方法吗?

更新的 只是为了澄清,我看到这段代码是&#34; hack&#34;我明白这很糟糕。我只是想知道什么可以打破以及为什么。

给出答案的一点摘要: 第((int*)arr)++;

1)仅在MSVS下编译不正确

2)产生一个sizeof(int)偏移量,导致以下地址被双边界错位。

这很清楚,但提出了另一个问题:演员本身是否允许从double *到int *?它会以任何方式影响alingment吗?

1 个答案:

答案 0 :(得分:4)

您发布的代码无效。原因很简单:malloc()返回与计算机上最大公共类型对齐的内存,这对double来说已足够,但是返回的内存用于在单个后存储double s int。在double为64位且int为32位(非常常见)的平台上,这不是有效代码,可能会崩溃或表现出比预期更差的性能。