繁体   English   中英

从函数(C)返回数组

[英]Returning array from function (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

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

static关键字用于在下次调用中“记住” r的值。 如果将其删除,则在函数返回时将清除分配给r的内存,因此您只是在返回垃圾。

当您有static 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;
}

请注意,我们必须如何free分配的内存(否则会发生内存泄漏)。 还要注意,我们必须处理NULL情况,在这种情况下我们无法分配必要的内存。

除少数情况外,表达式中的数组始终会衰减到其第一个元素的地址。
该指针是函数返回的值。
数组本身作为内存中的对象,通常会在函数执行完成后死亡。
因此,不能保证函数返回的指针所指向的内存地址会保留该数组,而可能会有垃圾。
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]);

因为您使用的是本地分配的数据; 一旦程序超出范围,则保存到其中的所有数据将被丢弃,并返回垃圾值。

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

要么malloc()一个指针数组,要么使用静态数组并返回其中之一。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM