C - 可以使用malloc返回值的数组(对齐)吗?

时间:2017-04-06 13:27:44

标签: c pointers alignment malloc

malloc通常用于为某些原始数据类型(intfloatchar)的 n 元素分配内存。这看起来像这样:

#define N 10

double *mem = malloc(N * sizeof(double));

for (int i = 0; i < N; ++i) {
  mem[i] = 10.0;       // Write
  double d = mem[i];   // Read
}

如果我将mem声明为char *并稍后使用了演员表,这甚至会有效:

char *mem = malloc(N * sizeof(double));

for (int i = 0; i < N; ++i) {
  *(double*)(mem + i * sizeof(double)) = 10.0;
  double d = *(double *)(mem + i * sizeof(double));
}

目前我想知道这是否定义良好并适用于每种数据类型(甚至任何复杂类型,如struct)。假设struct a可以是任何东西。以下是否定义明确?

char *mem = malloc(N * sizeof(struct a));

for (int i = 0; i < 10; ++i)) {
  *(struct a *)(mem + i * sizeof(struct a)) = /* something valid */;
  struct a x = *(struct a *)(mem + i * sizeof(struct a));
}

由于malloc的返回值适合于任何类型的变量,因此i = 0的情况明确定义并且有效,但I = 1, 2, ...怎么样?对齐螺丝将这个?就像在这个例子中一样:

char char_arr[4] = /* some value */;
int *d = &char_arr[0];

第二行无法保证正常工作,因为char_arr可能无法在4字节边界上对齐(int所需)。

2 个答案:

答案 0 :(得分:1)

是的,您可以使用malloc来分配结构数组。

  

7.22.3内存管理功能

     
      
  1. 通过连续调用分配的存储的顺序和连续性   未指定aligned_alloc,calloc,malloc和realloc函数。的的   指针返回如果分配成功被适当地对齐,以便可以将其分配给   指向具有基本对齐要求的任何类型对象的指针然后使用   在分配的空间中访问这样的对象或这些对象的数组(直到空间   明确解除分配)。 ...
  2.   

但你不需要做那些丑陋的演员:

struct a *mem = malloc(N * sizeof(struct a));

for (int i = 0; i < 10; ++i)) {
  mem[i] = /* something valid */;
  struct a var = mem[i];
}

答案 1 :(得分:1)

  

以下是否定义明确?

char *mem = malloc(N * sizeof(struct a));

for (int i = 0; i < N /* 10 */; ++i)) {
  *(struct a *)(mem + i * sizeof(struct a)) = /* something valid */;
  // struct a = *(struct a *)(mem + i * sizeof(struct a));
  struct a x = *(struct a *)(mem + i * sizeof(struct a));
}

几乎总是如此。

在对齐方面,*alloc()返回一个指向内存的指针,该指针对OP所记录的所有基本对齐都有效。 (struct a *)(mem + i * sizeof(struct a))还将为所有0 <= i <= N提供一个良好对齐的指针。

不太可能关注OP,但在稀有机器上i * sizeof(struct a)会溢出size_t数学(足够大isizeof(struct a),而mem[i]不会。在使用flat memory地址的常见实现中看不到。

同样强大的代码检查内存分配失败。

候选简化代码。请注意,ptr指向的类型不相关,假设它未定义void *ptr@usr

ptr = malloc(sizeof *ptr * N);
if (ptr == NULL) Handle_OOM();

for (size_t i = 0; i < N; ++i)) {
  ptr[i] = /* something valid */;
}

`