从函数(C)返回数组

时间:2016-10-16 22:36:35

标签: c

我对C编程非常陌生,我正在学习一些教程。困扰我的一件事是返回一个指向数组的指针。我已经从https://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm中删除了示例,以便最好地说明我的观点。

#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;
}

正如人们所料,这会打印

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) : 1
*(p + 2) : 2
*(p + 3) : 3
*(p + 4) : 4
*(p + 5) : 5
*(p + 6) : 6
*(p + 7) : 7
*(p + 8) : 8
*(p + 9) : 9

但是当你改变

   static int  r[10];

   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

我不明白为什么。我唯一能想到的是,由于某种原因,编译器将数组单元读取为不同的数据类型,但我怀疑这是对的。

5 个答案:

答案 0 :(得分:1)

static关键字用于“记住”下次通话中r的值。如果你删除它,那么当函数返回时,为r分配的内存会被刷新,所以你只是返回垃圾。

答案 1 :(得分:1)

当你有static int r[10];时,用于存储数组的内存在编译时分配,一切都按预期工作。

当你改为int r[10]时,你在运行时堆栈帧上分配你的数组,当函数调用返回时它变得无效,然后被下一个函数调用覆盖,所以你看到垃圾。

答案 2 :(得分:0)

原因是当您在没有静态数组声明的情况下调用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;
}

注意我们必须free我们分配的内存(否则我们会有内存泄漏)。另请注意,我们必须处理NULL情况,我们无法分配必要的内存。

答案 3 :(得分:0)

除少数情况外,表达式中的数组总是衰减到其第一个元素的地址 该指针是函数返回的值 作为生活在内存中的对象,数组本身通常在函数执行完成后死亡 因此,函数返回的指针指向的内存地址不能保证保留数组,而是可能有垃圾 static声明保留了数组对象,但是你的函数仍然返回一个指向数组头部的指针而不是数组本身。
将指针返回到函数的内部static对象是不好的做法, 因为您允许函数的任何用户以不可预知的方式从函数外部更改数组的值。
如果要返回一个完整的数组作为值,也许你应该用这种方式定义一个包含数组字段的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]);

答案 4 :(得分:0)

因为您使用的是本地分配的数据;一旦程序超出范围,那么保存到它的所有数据都会被抛出,它将返回垃圾值。

在这种情况下,你可以做两件事:

malloc()指针数组或使用静态数组并返回其中一个。

您可以做的另一个选择是在函数参数中放置一个数组缓冲区,以便将数据复制到该缓冲区。