如何从函数A返回一个数组,然后函数B接受此数组

时间:2019-01-03 20:28:31

标签: c arrays pointers

我的主要职能有两个职能。

我试图用指针来解决这个问题,但是作为一个初学者,使用它是非常复杂的。

int main(){
  int *p;

  p = function_A();
  function_B(p);

  return 0; 
}

int function_A(){
  static int myArray[3];
  myArray[0] = 11;
  myArray[1] = 22;
  myArray[2] = 33;

  return myArray;
}

int function_B(int *myPointer){
  // Here I just want to print my array I've got from function_A() to the 
  // console

  printf("%d", *myPointer)
  return 0;
}

function_A应该返回一个数组,而function_B应该使用这个数组。

谢谢!

4 个答案:

答案 0 :(得分:2)

您的编译器已经告诉您一些问题。 首先,您应该在调用函数之前定义它们,或者至少向前声明它们。

第二,要返回一个数组,您需要返回一个指向该数组第一个元素的指针,即返回类型为int *而不是int

第三,正如FredK所指出的那样,当您仅收到一个指针时,就没有机会确定它所指向的数组中有多少个元素。您可以使用特定值终止数组,例如0,否则您也需要返回数组的大小。

请参阅对程序进行的以下修改:

int* function_A(int *size){
    static int myArray[3];
    myArray[0] = 11;
    myArray[1] = 22;
    myArray[2] = 33;

    if (size) {
        *size = 3;
    }
    return myArray;
}

void function_B(int *myPointer, int size){
    for (int i=0; i<size; i++) {
        printf("%d\n", myPointer[i]);
    }
}

int main(){
    int *p;

    int size=0;
    p = function_A(&size);
    function_B(p,size);

    return 0;
}

答案 1 :(得分:0)

注意:对数组的引用会降级为数组第一个字节的地址。

以下建议的代码:

  1. 干净地编译
  2. 将评论纳入问题
  3. 假设程序员已经知道数组的大小
  4. 执行所需的功能
  5. 附加了'\ n'来格式化对printf()的调用字符串,以便在单独的行上输出

现在,建议的代码:

#include <stdio.h>


int * function_A( void );
void  function_B(int *myPointer);

int main( void )
{
  int *p;

  p = function_A();
  function_B(p);

  return 0; 
}


int * function_A()
{
  static int myArray[3];
  myArray[0] = 11;
  myArray[1] = 22;
  myArray[2] = 33;

  return myArray;
}

void function_B(int *myPointer)
{
  printf("%d\n", myPointer[0]);
  printf("%d\n", myPointer[1]);
  printf("%d\n", myPointer[2]);
}

程序运行将产生以下输出:

11
22
33

答案 2 :(得分:0)

假设您有一个创建int s数组的函数:

int *create_int_array(const size_t num)
{
    int    *iarray;
    size_t  i;

    if (num < 1)
        return NULL; /* Let's not return an empty array. */

    iarray = malloc(num * sizeof iarray[0]);
    if (!iarray)
        return NULL; /* Out of memory! */

    /* Fill in the array with increasing integers. */
    for (i = 0; i < num; i++)
        iarray[i] = i + 1;

    return iarray;
}

比方说,tou具有一个计算数组中整数和的函数。如果我们忽略任何溢出问题,它可能看起来像这样:

int sum_int_array(const int *iarray, const size_t num)
{
    int    sum = 0;
    size_t i;

    /* Sum of an empty array is 0. */
    if (num < 1)
        return 0;

    for (i = 0; i < num; i++)
        sum += iarray[i];

    return sum;
}

请注意,sizeof不是函数,而是C语言关键字。仅检查其参数的大小。因此,sizeof iarray[0]得出iarray中每个元素的大小,并且即使此时iarray未定义或为NULL也完全安全有效。您会在C程序中看到很多习惯用法;学习将其读取为“ iarray的第一个元素的大小” ,与“ iarray的每个元素的大小” 相同,因为所有C数组元素都具有大小相同。

在您的main()中,您可以这样称呼他们:

#ifndef  NUM
#define  NUM  5
#endif

int main(void)
{
    int  *array, result;

    array = create_int_array(NUM);
    if (!array) {
        fprintf(stderr, "Out of memory!\n");
        exit(EXIT_FAILURE);
    }

    result = sum_int_array(array, NUM);

    printf("Sum is %d.\n", result);

    free(array);

    return EXIT_SUCCESS;
}

如您所见,确实没有太多内容。好吧,您确实需要熟悉指针语法。

(我想指出的规则是,在读取指针类型时,请从右向左读取说明符,并以*分隔,并以指向的指针的形式来表示。因此,{{ 1}}读为“ a是一个const,指向int的指针” ,而int *const a读为“ b是一个指向const char的指针” 。)


在这种情况下,描述数组的结构更有意义。例如:

const char **b

这个想法是,您可以像声明任何其他变量一样声明typedef struct { size_t max; /* Maximum number of elements val[] can hold */ size_t num; /* Number of elements in val[] */ int *val; } iarray; #define IARRAY_INIT { 0, 0, NULL } 类型的变量。但您也可以使用iarray宏将其初始化为空数组。换句话说:

IARRAY_INIT

使用该初始化,结构总是被初始化为已知状态,我们不需要单独的初始化函数。我们真的只需要几个辅助函数:

    iarray  my_array = IARRAY_INIT;

static inline void iarray_free(iarray *array) { if (array) { free(array->val); array->max = 0; array->num = 0; array->val = NULL; } } /* Try to grow the array dynamically. Returns the number of elements that can be added right now. */ static inline size_t iarray_need(iarray *array, const size_t more) { if (!array) return 0; if (array->num + more > array->max) { size_t max = array->num + more; void *val; /* Optional: Growth policy. Instead of allocating exactly as much memory as needed, we allocate more, in the hopes that this reduces the number of realloc() calls, which tend to be a bit slow. However, we don't want to waste too much memory by allocating and then not using it. */ if (max < 16) { /* Always allocate at least 16 elements, */ max = 16; } else if (max < 65536) { /* up to 65535 elements add 50% extra, */ max = (3*max) / 2; } else { /* then round up to next multiple of 65536, less 16. */ max = (max | 65535) + 65521; } val = realloc(array->val, max * sizeof array->val[0]); if (!val) { /* We cannot grow the array. However, the old array is still intact; realloc() does not free it if it fails. */ return array->max - array->num; } /* Note: the new elements in array->val, array->val[array->max] to array->val[max-1], inclusive, are undefined. That is fine, usually, but might be important in some special cases like resizing hash tables or such. */ array->max = max; array->val = val; } return array->max - array->num; } /* Optional; same as initializing the variable to IARRAY_INIT. */ static inline void iarray_init(iarray *array) { array->max = 0; array->num = 0; array->val = NULL; } 位意味着功能仅在此编译单元中可见,并且编译器可以自由地直接在调用站点上实现该功能。基本上,static inline用于类似宏的函数和访问器函数。如果将结构放在头文件(.h)中,则还将其中的相关static inline辅助函数也放入其中。

增长政策部分只是一个示例。如果您省略增长策略,并且始终将其重新分配给static inline元素,则您的代码将非常频繁地调用array->num + more,可能会为每个附加的realloc()调用。在大多数情况下,这样做通常会减慢您的程序速度,因为int(以及realloc()malloc())有点慢。为了避免这种情况,我们宁愿稍微增加或舍入分配:不要浪费太多,浪费已分配但没有使用的内存,但足以使整个程序保持快速运行,并且不会因太多calloc()调用而成为瓶颈。 >

“良好的增长政策”在很大程度上尚待争论,并且实际上取决于眼前的任务。当程序仅需要一个或少数几个这样的阵列时,上面的程序应该在台式机,笔记本电脑和平板电脑上的所有当前操作系统上都能很好地工作。

(如果程序使用许多这样的数组,它可能会实现一个realloc()函数,该函数会将数组重新分配给它所拥有的元素的确切数目。每当数组不太可能很快改变大小时,调用该函数都会确保没有过多的内存未使用但在数组中分配了。)

让我们看一个使用上面的示例函数。说,显而易见的一个:在数组后附加一个整数:

iarray_optimize()

另一个示例函数将是按升序或降序对数组中的/* Append an int to the array. Returns 0 if success, nonzero if an error occurs. */ int iarray_append(iarray *array, int value) { if (!array) return -1; /* NULL array specified! */ if (iarray_need(array, 1) < 1) return -2; /* Not enough memory to grow the array. */ array->val[array->num++] = value; return 0; } 进行排序的函数:

int

许多新程序员都没有意识到标准C库具有用于排序数组的漂亮而高效的qsort()函数;它所需要的只是一个比较功能。如果static int cmp_int_ascending(const void *ptr1, const void *ptr2) { const int val1 = *(const int *)ptr1; const int val2 = *(const int *)ptr2; return (val1 < val2) ? -1 : (val1 > val2) ? +1 : 0; } static int cmp_int_descending(const void *ptr1, const void *ptr2) { const int val1 = *(const int *)ptr1; const int val2 = *(const int *)ptr2; return (val1 < val2) ? +1 : (val1 > val2) ? -1 : 0; } static void iarray_sort(iarray *array, int direction) { if (array && array->num > 1) { if (direction > 0) qsort(array->val, array->num, sizeof array->val[0], cmp_int_ascending); else if (direction < 0) qsort(array->val, array->num, sizeof array->val[0], cmp_int_descending); } } direction为正,则该数组以升序排序,最小的iarray_sort()首先;反之,则最小。如果int为负数,则以降序排列,最大direction首先。

一个简单的示例int,它从标准输入中读取所有有效的main(),对它们进行排序,然后以升序(增值)打印它们:

int

答案 3 :(得分:0)

如果数组的大小确实为3(或其他小的固定值),则可以简单地将结构用作值,例如:

struct ints3 {
  int values[3];
  // if needed, can add other fields
}

int main(){
  struct ints3 ints;

  ints = function_A();
  function_B(&ints);

  return 0; 
}

// note about function_A signature: void is important,
// because in C empty () means function can take any arguments...
struct ints3 function_A(void) {
  // use C designated initialiser syntax to create struct value,
  // and return it directly
  return (struct ints3){ .values = { 11, 22, 33 } };
}

int function_B(const struct ints3 *ints) {
  // pass struct as const pointer to avoid copy,
  // though difference to just passing a value in this case is insignificant

  // could use for loop, see other answers, but it's just 3 values, so:
  printf("%d %d %d\n", ints->values[0], ints->values[1], ints->values[2]);
  return 0; // does this function really need return value?
}