在函数中使用malloc分配数组并从外部访问该数组的C语言问题

5

以下是我如何使用malloc分配一个整数变量,并在函数外访问该变量的方法

int f1(int ** b) {
  *b = malloc(sizeof(int)); 
  **b = 5;
}

int main() {
  int * a;
  f1(&a);
  printf("%d\n", *a);
  // keep it clean : 
  free(a);
  return 0;
}

使用上述相同的逻辑,我该如何在函数内部malloc一个一维数组,然后在函数外部访问它?
请帮忙,我对指向数组的指针有点困惑。

1
天哪!为什么不用 int* f1(int size) 并且 返回 指针呢?这样更符合惯用法,特别是在上面你没有使用返回值的情况下。 - dmckee --- ex-moderator kitten
@dmckee:你能写完整的代码吗?谢谢。 - ihtus
5个回答

16

用完全相同的方式,只是进行一些不同的算术运算。您可以将现在正在进行的操作视为分配具有一个元素的数组。只需将sizeof(int)乘以您想要数组拥有的元素数量即可:

int f1(int ** b, int arrsize) {
  *b = malloc(sizeof(int) * arrsize);

  // then to assign items:
  (*b)[0] = 0;
  (*b)[1] = 1;
  // etc, or you can do it in a loop
}

int main() {
  int * a, i;
  int size = 20;

  f1(&a, size); // array of 20 ints

  for (i = 0; i < size; ++i)
      printf("%d\n", a[i]); // a[i] is the same as *(a + i)
                            // so a[0] is the same as *a

  // keep it clean : 
  free(a);

  return 0;
}

我该如何在f1函数内给数组赋值? - ihtus
@ihtus 像这样:(*b)[x] = y,其中 x 是索引,例如第一个项目为 0,第二个项目为 1,以此类推,而 y 是您想要分配给该索引的项目。我在我的帖子中添加了一个示例。 - Seth Carnegie
@Seth 我有一个问题。如果我想从一个函数中返回一个固定大小的字符数组,那么是更好地在函数外分配内存然后传递指针,还是在函数内部分配数组然后返回指向该数组的指针呢?(就最佳编程实践而言) - 4aRk Kn1gh7

2
你已经接近成功了。 *b = malloc(sizeof(int)); 分配了单个int的空间(有点没有意义,因为指针至少与此一样大)。
更常见的用法是 *b = malloc(number_of_ints*sizeof(int)); 记住,[] 语法只是为您执行数组数学计算,(a+10)a[10] 指向完全相同的内存位置,因此您可以使用malloc分配它,传递指针并将其表示为数组。
关于数组和指针的唯一复杂之处(除了记住何时使用*和&)就是malloc()按字节工作,因此您需要告诉它int的sizeof。但是,它返回的 int * 知道int,因此要访问下一个值,您只需要执行 a++a+1a[1],即使在值上实际上相差4或8个字节。

2
a+10a[10] 不同,但是 *(a+10)a[10] 是相同的。 - Dan
1
@Dan - 很好的观点,当教授新手时最好要准确无误。 - Martin Beckett
1
实际上,如果你很严谨的话,a++并不能像a+1或者a[1]那样让你到达下一个元素,你需要使用++a来实现 :) - Seth Carnegie

2

(未经测试,但我相信它会起作用)

(未经测试,但我认为它会有效)
int f1(int ** b) {
  *b = malloc(sizeof(int)*4); 

  (*b)[0] = 5;
  (*b)[1] = 6;
  (*b)[2] = 7;
  (*b)[3] = 8;
}

int main() {
  int * a;
  f1(&a);
  printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]); // should be "5 6 7 8"
  // keep it clean : 
  free(a);
  return 0;
}

(*b)[0] = 5 是唯一的赋值方式吗?以下是 Dan 使用的 *b = 5; b[1] = 6; *(b + 2) = 7; 但这对我不起作用。 - ihtus
1
我相信你也可以执行*((*b)+1) = 6; - abelenky

0

不需要,malloc工作得很好。只有在需要零填充时才需要使用calloc,这通常仅对字符串必要。 - Dan
在Unix系统上它们是相同的,而在其他系统上,如果您不需要将所有值都设置为零,为什么要承担这样的开销呢? - Martin Beckett

0

不要使用malloc()来分配单个整数,而应该使用malloc来分配数组。

int f1(int * b) {
  b = malloc(ARRAY_LENGTH * sizeof(int)); 
  *b = 5;
  b[1] = 6;
  *(b + 2) = 7;
}

2
我认为那样做行不通。你在b上没有足够的解引用。因此,当这个函数返回时,内存仍然被分配,但是父范围中的变量不再指向已分配的内存。 - abelenky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接