我编写了一个函数,该函数创建一个数据表,将其元素初始化为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;
}
答案 0 :(得分:2)
函数终止时,其所有自动变量将超出范围。
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?
答案 1 :(得分: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;
}
答案 2 :(得分:1)
这里:
// 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)。