【问题标题】:Returning a pointer to an array返回指向数组的指针
【发布时间】:2018-11-13 16:36:51
【问题描述】:

我编写了一个函数来创建一个数据表,将它的元素初始化为 0 并返回一个指向数据表的指针。但是它不起作用。有人可以向我解释一下,以便我了解我的问题所在。 这是我的代码:

#include <stdio.h>

// Here I create the data table and initialize it's elements
int* tabinit(int size) {
  int tab[size];

  for (int i = 0; i < size; i++)
    tab[i] = 0;
  return tab;
}

int main() {
  int* t = tabinit(10);

  for (int i = 0; i < 10; i++)
    printf("%d ", t[i]);
  printf("\n");
  return 0;
}

【问题讨论】:

标签: c arrays function pointers


【解决方案1】:

当一个函数终止时,它的所有自动变量都会超出范围

tab 在这种情况下是一个自动变量,当函数终止时将超出范围。现在您将一个指针返回到一个本地数组,所以当数组超出范围时,您会发现自己有一个dangling pointer .

你的编译器没有警告过你吗?我在 GCC 中收到了这个警告:

warning: function returns address of local variable [-Wreturn-local-addr]
   return tab;
          ^~~

首先确定你真的想要练习在函数中创建数组。如果没有,那么你不需要,你可以在 main 中创建,然后将其传递给函数。

但是,如果您想练习,那么您需要动态分配数组,如果您真的希望它在函数终止后保持活动状态。在这种情况下,数组将释放它的内存,只有当你告诉它时(所以永远不要忘记释放)。

例子:

#include <stdio.h>
#include <stdlib.h>


int* tabinit(int size) {
  int *tab = malloc(size * sizeof(int));

  for (int i = 0; i < size; i++)
    tab[i] = 0;
  return tab;
}

int main() {
  int* t = tabinit(10);

  for (int i = 0; i < 10; i++)
    printf("%d ", t[i]);
  printf("\n");

  // do NOT forget to free
  free(t);

  return 0;
}

输出:

0 0 0 0 0 0 0 0 0 0

PS:当你对malloc()更加熟悉的时候,我建议你阅读这个:Should I check if malloc() was successful?

【讨论】:

  • 听起来你的“malloc()”编辑和我的答案在 2 分钟内得到验证,所以几乎同时......我现在不知道如何处理我的答案。唯一不重复的部分是关于内存泄漏问题的行。
  • @Amessihel 我认为您的回答很有用,因为它丰富了图形。 :)
  • @gsamaras 你能解释一下这条线的作用吗int *tab = malloc(size * sizeof(int));
  • @MisterTusk 它动态分配与size * sizeof(int) 一样大的内存并使tab 指向该内存。 sizeof(int) 是一个数字,可能因机器而异。例如,在你的可能是 4。
【解决方案2】:

你永远不应该返回一个指向本地对象的指针。函数完成后,本地对象被解除分配,剩下一个悬空指针(不指向有效内存的指针)。

一种方法是在 main 中创建您的对象并将其传递给您的 init 函数,如下所示:

void tabinit(int* tab, int size) {
  for (int i = 0; i < size; i++)
    tab[i] = 0;
}

int main() {
  int t[10];
  tabinit(t, 10);

  for (int i = 0; i < 10; i++)
    printf("%d ", t[i]);
  printf("\n");
  return 0;
}

【讨论】:

  • tabinit(&amp;t, 10); 更改为tabinit(t, 10);。我喜欢你的回答,但你上次的编辑是错误的,所以请修正它。
  • @gsamaras 为什么我们不能在这里使用 &t?
  • @MisterTusk 因为参数类型是int*,而t是一个数组。这将是不相容的。我建议你把它编译出来并阅读警告信息,它非常有启发性!
【解决方案3】:

这里:

// Here I create the data table and initialize it's elements
int* tabinit(int size) {
  int tab[size]; // <------- here

  for (int i = 0; i < size; i++)
    tab[i] = 0;
  return tab;    // <------- also here
}

正如 gsamaras 所说,tab 指向的内容在函数调用后超出范围。您可以更改此行:

int tab[size];

作者:

int *tab;
tab = malloc(size * sizeof(int));

内容会被动态分配,退出函数后会保留。但是,您必须在之后手动释放它 (free(t)),否则它将被保留到程序结束(可能会出现 memory leak)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 2013-04-10
    相关资源
    最近更新 更多