繁体   English   中英

如何从C函数创建数组返回类型?

[英]How to make an array return type from C function?

我试图返回数组名称,如下所示。 基本上我试图让函数 test 返回一个可以在 main 中使用的数组。 你能告诉我我需要阅读更多内容以了解如何执行这样的功能吗?

#include <stdio.h>

int test(int size, int x){
    int factorFunction[size];    
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
    return factorFunction;
}

int main(void){
    int factors[2];
    factors = test(2, 3);
    printf("%d", factors[1]);
    return 0;
}

我收到编译器错误:

smallestMultiple.c:8: warning: return makes integer from pointer without a cast
smallestMultiple.c:8: warning: function returns address of local variable
smallestMultiple.c: In function ‘main’:
smallestMultiple.c:13: error: incompatible types in assignment

函数不能在 C 中返回数组。

但是,它们可以返回结构。 结构可以包含数组...

您可以通过返回一个指针来返回一个数组(数组衰减为指针)。 但是,这在您的情况下会很糟糕,因为您将返回一个指向局部变量的指针,这会导致未定义的行为。 这是因为函数返回后返回的指针指向的内存不再有效,因为堆栈空间现在被其他函数重用。

您应该做的是将数组及其大小都作为参数传递给函数。

您的代码中还有另一个问题,那就是您使用了大小为 2 的数组,但写入了第三个元素。

您需要在堆上分配内存并返回一个指针。 C 不能从函数返回数组。

int* test(int size, int x)
{
    int* factorFunction = malloc(sizeof(int) * size);    
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
    return factorFunction;
}

错误消息的第一行正是它所说的意思:您已将函数声明为返回一个int ,但您尝试返回一个指针。
更大的问题(如错误消息的第二行告诉您的)是您尝试返回指针的数组是本地数组,因此当函数返回时将超出范围并且不再有效。
你应该做的是使用mallocnew动态分配一个数组(即一块连续内存)并返回一个指向它的指针。 当然,请确保在完成后释放内存。

不幸的是,C 不支持从函数返回任意数组或匿名结构,但有两种解决方法。

第一个解决方法是创建一个包含数组的结构。 它将与数组具有相同的大小,在堆栈上分配以确保空间局部性。

例如

typedef struct {
    int arr[5];
} my_array1;

typedef struct {
    int values[3];
} factorFunctionReturnType_t;

第二种解决方法是创建一个静态内存池(例如,仅针对该数组使用自定义 malloc/free 的数组),这将有效地允许您从此池中动态分配内存,再次有效地返回指向连续堆栈空间的指针,从而根据定义是一个数组。

例如

#include <stdint.h>
static uint8_t static_pool[2048];

然后实现管理这个特定内存池的 my_alloc、my_free,再次确保创建的内存在堆栈上,并且内存已经被你的应用程序先验拥有(而 malloc 可能会分配之前应用程序无法访问的内存,或者如果内存不足则崩溃并且没有检查失败返回)。

第三种解决方法是让函数返回一个局部变量给回调函数; 这确保一旦函数完成,您可以使用结果而不会破坏堆栈,因为使用内存的函数将位于包含堆栈的作用域之上。

#include <stdint.h>
#include <stdio.h>

void returnsAnArray(void (*accept)(void *)) {
    char result[] = "Hello, World!";    

    accept(result);
}

void on_accept(void *result) {
    puts((char *)result);
}

int main(int argc, char **argv)
{
    returnsAnArray(on_accept);

    return 0;
}

这比需要做出决定以避免碎片的非堆栈式内存池更有效,比仅将结果放在堆栈顶部的堆栈式内存池更有效,因为它不需要复制字符串,等等线程安全,因为函数的返回值不会有被另一个线程覆盖的风险(除非使用了锁)。

有趣的是,所有“函数式编程范式”程序最终都强调您可以通过链接回调函数在没有任何 malloc 的情况下编写 C 程序,有效地在堆栈上分配。

这有一个有趣的副作用,使链表不再缓存敌对(因为分配在堆栈上的回调链表都将在堆栈上彼此靠近,这使您可以在没有任何 malloc 的情况下执行运行时字符串操作等操作,并让您在不执行任何 malloc 的情况下构建了未知大小的用户输入。

C 不提倡将局部变量的地址返回给函数外部,因此您必须将局部变量定义为静态变量。

#include <stdio.h>

/* function to generate and return random numbers */
int * getRandom( ) {

   static int  r[10];
   int i;

   /* set the seed */
   srand( (unsigned)time( NULL ) );

   for ( i = 0; i < 10; ++i) {
      r[i] = rand();
      printf( "r[%d] = %d\n", i, r[i]);
   }

   return r;
}

/* main function to call above defined function */
int main () {

   /* a pointer to an int */
   int *p;
   int i;

   p = getRandom();

   for ( i = 0; i < 10; i++ ) {
      printf( "*(p + %d) : %d\n", i, *(p + i));
   }

   return 0;
}
#include <stdio.h>

#include <stdlib.h>

int* test(int size, int x){
    int *factorFunction = (int *) malloc(sizeof(int) * size);    
    if( factorFunction != NULL ) //makes sure malloc was successful
    {
        factorFunction[0] = 5 + x;
        factorFunction[1] = 7 + x;
        factorFunction[2] = 9 + x; //this line won't work because your array is only 2 ints long

    }
return factorFunction;
}

int main(void){
    int *factors;
    factors = test(2, 3);
    printf("%d", factors[1]);
    //just remember to free the variable back to the heap when you're done
    free(factors);
    return 0;
}

您可能还想确保您设置的索引确实存在于您的数组中,正如我上面提到的

首先,除非你有带有VLA的 C99,否则数组大小在 C 中应该是常量。你不能使用下面的语句:

int factorFunction[size];

其次,您试图返回一个在函数中创建的数组,该数组将被删除到范围之外。

为了避免这种情况,您可以在测试函数中将数组作为参数或使用malloc函数动态创建数组。 顺便说一句,您的test函数可以返回指向更新数组的指针。

我的建议是传入一个数组来填充:

void test(int size, int factors[], int x){
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
}

int main(void){
    int factors[3];
    test(3, factors, 3);
    printf("%d", factors[1]);
    return 0;
}

使用这种方法,您不必担心分配,也不需要稍后释放数组。

我还修正了数组的大小,所以你不要在它之外写第三个元素。 请记住,C数组声明与“你想要多少”,然后从索引0 ... (how_many-1)所以[2]数组上宣布[2]进入阵列外部。

这是传回数组的另一种方法:

    int test(){
        static int factorFunction[3];    
        factorFunction[0] = 5 + x;
        factorFunction[1] = 7 + x;
        factorFunction[2] = 9 + x;
        return factorFunction;
    }

静态表示变量将以保留在内存中的方式分配。 因此,如果您有一个固定大小的值并希望它在函数调用之间保留在内存中,这是一种方法。

首先,您不能直接从 C 中的函数返回数组。 您可以做的是,您可以在该函数中返回数组的地址。 在这种情况下,该函数将如下所示:

int* test(int size, int x){

    /* function body */

    return factorFunction;
}

要接收数组,您将需要一个指针 - 而不是数组。

所以,而不是使用int factors[2]; 你必须使用int *factors; 在您的main功能中。

其次,即使你返回数组的地址,这段代码也不起作用; 因为您正在尝试返回本地数组的地址; 在函数执行后将不存在。 解决此问题的一种简单方法是将本地数组(在本例中为factorFunction )声明为静态。

考虑到这两点,功能test将如下所示:

int* test(int size, int x){

    static int factorFunction[size];

    /* function body */

    return factorFunction;
}

要记住的两点:

  1. 如果要从函数返回单维数组,则必须声明一个返回指针的函数。

  2. C 不提倡将局部变量的地址返回给函数外部,因此您必须将局部变量定义为静态变量。

请参阅此链接: https : //www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm

  // example for to create a array in function and it return using pointer
  //if you want use malloc use header #include <stdlib.h>
      int * printsquares(int a[],int size){  //to declare aa function

      int* e = malloc(sizeof(int) * size);  //to create array using malloc
       for(int i=0;i<size;i++){    
             e[i]=i*i;       //assign the square root values
      }



   return e;


 }

关于如何将数组从用户定义的函数返回到主函数的非常基本的代码解释希望它有所帮助。 下面,我写了一个完整的代码来制作。 请原谅 C++ 语言,但是如果您完全需要 C 程序,请随时发表评论

#include<iostream>
using namespace std;

int * function_Random()// function with returning pointer type of integer
{
     static int arr[100];
     cout<<"We are Inside FunctionRandom"<<endl;
    for(int i=0;i<100;i++)//loop to add elements in array
    {
        arr[i]=rand();//rand() function to put random numbers generated by system
        cout<<"\t"<<arr[i]; //to show how our array will look
    }
    cout<<endl<<endl;//endl for end line to look well formatted 
    return arr;
}
int main()
{


    int *arrptr; //pointer to get back base address of array
    arrptr=function_Random();//function that returns base address
    cout<<"We are Inside Main"<<endl;
    for(int j=0;j<100;j++)
    {
         cout<<"\t"<<arrptr[j];//returned base address has complete link of array that's why it is able to print the array:contiguous memory locations.
    }       
    return 0;//nothing to return that's why 0
}

暂无
暂无

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

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