从函数(C)返回数组
我对C编程非常陌生,正在学习一些教程。有一件事难住了我,那就是返回指向数组的指针。我把这个例子从中删去,以便最好地说明我的观点从函数(C)返回数组,c,C,我对C编程非常陌生,正在学习一些教程。有一件事难住了我,那就是返回指向数组的指针。我把这个例子从中删去,以便最好地说明我的观点 #include <stdio.h> int * getRandom( ) { static int r[10]; int i; for ( i = 0; i < 10; ++i) { r[i] = i; printf( "r[%d] = %d\n", i, r[i]); } return
#include <stdio.h>
int * getRandom( ) {
static int r[10];
int i;
for ( i = 0; i < 10; ++i) {
r[i] = i;
printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}
int main () {
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
return 0;
}
但是当你改变的时候
static int r[10];
到
而是打印
r[0] = 0
r[1] = 1
r[2] = 2
r[3] = 3
r[4] = 4
r[5] = 5
r[6] = 6
r[7] = 7
r[8] = 8
r[9] = 9
*(p + 0) : 0
*(p + 1) : 1980517315
*(p + 2) : -1164399724
*(p + 3) : 4199040
*(p + 4) : 4199040
*(p + 5) : 2285568
*(p + 6) : 19
*(p + 7) : 6356668
*(p + 8) : 8
*(p + 9) : 6356940
我不知道为什么。我能想到的唯一一件事是,出于某种原因,编译器正在将数组单元格读取为不同的数据类型,但我怀疑这是正确的。在下一次调用中,使用
static
关键字“记住”r
的值。如果您删除它,那么当函数返回时,分配给r
的内存将被刷新,因此您只是返回垃圾。当您有静态int r[10]代码>,用于存储数组的内存在编译时分配,并且一切正常
当您使用int r[10]
时,您是在运行时堆栈帧上分配数组,当函数调用返回时,该堆栈帧无效,然后被下一个函数调用覆盖,因此您会看到垃圾。原因是当您在没有静态数组声明的情况下调用getRandom()
时,一旦getRandom()
函数返回,数组就不在作用域内。这意味着您的指针可能不再“指向”r,因为r实际上已被丢弃
为了正确地从getRandom()
返回,您需要使用malloc
动态分配内存,例如:
int * getRandom( ) {
int *r = NULL;
r = malloc(sizeof(int) * 10); /* Create room for 10 integers*/
if (r == NULL) {
printf("Error: Could not allocate space\n");
return NULL;
}
int i;
for ( i = 0; i < 10; ++i) {
r[i] = i;
printf( "r[%d] = %d\n", i, r[i]);
}
return r; /* Returns a pointer to r*/
}
int main () {
int *p;
int i;
p = getRandom();
if (p == NULL) {
/*Error state*/
return 1;
}
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
free(p); /* Free the memory we allocated*/
return 0;
}
int*getRandom(){
int*r=NULL;
r=malloc(sizeof(int)*10);/*为10个整数创建空间*/
if(r==NULL){
printf(“错误:无法分配空间\n”);
返回NULL;
}
int i;
对于(i=0;i<10;++i){
r[i]=i;
printf(“r[%d]=%d\n”,i,r[i]);
}
返回r;/*返回指向r的指针*/
}
int main(){
int*p;
int i;
p=getRandom();
if(p==NULL){
/*错误状态*/
返回1;
}
对于(i=0;i<10;i++){
printf(“*(p+%d):%d\n”,i,*(p+i));
}
释放(p);/*释放我们分配的内存*/
返回0;
}
请注意,我们必须释放分配的内存(否则我们将有内存泄漏)。还请注意,我们必须处理NULL
情况,在这种情况下,我们无法分配必要的内存。除了少数情况外,表达式中的数组总是衰减到其第一个元素的地址。
此指针是函数返回的值。
作为内存中的对象,数组本身通常在函数执行完成后死亡。
因此,函数返回的指针指向的内存地址不能保证保留数组,它可能会有垃圾。
静态
声明保留数组对象,但函数仍然返回指向数组头的指针,而不是数组本身。
返回指向函数内部静态
对象的指针是不好的做法,
因为您允许函数的任何用户以多种可预测的方式从函数外部更改数组的值。
如果要将完整数组作为值返回,可能需要定义一个包含数组字段的struct
类型,方法如下:
typedef struct { int sub[10]; } wrappedarray_t;
wrappedarray_t getRandom(void) {
wrappedarray_t r;
// sentences....
return r;
}
wrappedarray_t p = getRandom();
printf("0th element: %d\n", p.sub[0]);
因为您使用的是本地分配的数据;一旦程序超出范围,那么保存到其中的所有数据都将被抛出,并返回垃圾值
在这种情况下,您可以做两件事:
malloc()
指针数组或使用静态数组并返回其中一个
您可以做的另一个选择是在函数参数中放入数组缓冲区,以便将数据复制到该缓冲区。阅读编译器警告:返回对临时的引用不好。这意味着值将随时被覆盖(因此使用static关键字)。找不到此的副本。感谢所有回复;我想我现在明白了。因此,本质上,一旦您离开getRandom函数,用于数组其余部分的内存将被重新分配,但这可以通过为函数输出分配堆栈内存的“malloc()”绕过。
int * getRandom( ) {
int *r = NULL;
r = malloc(sizeof(int) * 10); /* Create room for 10 integers*/
if (r == NULL) {
printf("Error: Could not allocate space\n");
return NULL;
}
int i;
for ( i = 0; i < 10; ++i) {
r[i] = i;
printf( "r[%d] = %d\n", i, r[i]);
}
return r; /* Returns a pointer to r*/
}
int main () {
int *p;
int i;
p = getRandom();
if (p == NULL) {
/*Error state*/
return 1;
}
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
free(p); /* Free the memory we allocated*/
return 0;
}
typedef struct { int sub[10]; } wrappedarray_t;
wrappedarray_t getRandom(void) {
wrappedarray_t r;
// sentences....
return r;
}
wrappedarray_t p = getRandom();
printf("0th element: %d\n", p.sub[0]);