Подтвердить что ты не робот

Как сделать тип возвращаемого массива функцией C?

Я попытался вернуть имя массива, как показано ниже. В основном я пытаюсь вернуть функцию test массиву, который можно использовать в основном. Не могли бы вы посоветовать мне, что мне нужно прочитать, чтобы узнать, как выполнить такую ​​функцию?

#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
4b9b3361

Ответ 1

Функции не могут возвращать массивы в C.

Однако они могут возвращать структуры. А структуры могут содержать массивы...

Ответ 2

Вы можете вернуть массив, вернув указатель (массивы распадутся на указатели). Тем не менее, это было бы плохо в вашем случае, так как тогда вы возвращали бы указатель на локальную переменную и приводили к поведению undefined. Это связано с тем, что память, на которую указывает возвращенный указатель, больше не действует после возвращения функции, поскольку пространство стека теперь снова используется другими функциями.

Что вы должны сделать, так это передать массив и его размер как аргументы функции.

У вас также есть другая проблема в вашем коде, и вы используете массив размером два, но пишите в третий элемент.

Ответ 3

Вам нужно будет выделить память в куче и вернуть указатель. 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;
}

Ответ 4

Первая строка сообщений об ошибках означает именно то, что она говорит: вы объявили функцию как возвращающую int, но вы пытаетесь вернуть указатель.
Большая проблема (как говорит вторая строка сообщений об ошибках) заключается в том, что массив, к которому вы пытаетесь вернуть указатель, является локальным массивом и, следовательно, выходит из области действия, когда функции возвращаются и перестают быть действительными.
То, что вам нужно сделать, - это динамически выделить массив (т.е. кусок непрерывной памяти) с помощью malloc или new и вернуть указатель на него. И, конечно же, убедитесь, что вы освобождаете память, когда закончите с ней.

Ответ 5

К сожалению, 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, которые управляют этим конкретным пулом памяти, снова гарантируя, что созданная память находится в стеке, а память уже принадлежит вашему приложению apriori (тогда как 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;
}

Это более эффективно, чем пул памяти, не содержащий стека, который должен принимать решения во избежание фрагментации, более эффективный, чем пул в виде стека, который просто помещает результат поверх стека, потому что ему не нужно копировать строку, и более потокобезопасными, потому что возвращаемое значение функции не может быть перезаписано другим потоком (если не используется блокировка).

Самое смешное, что все "парадигмы функционального программирования" в конечном итоге подчеркивают, что вы можете писать программы на C без какого-либо malloc путем цепочки функций обратного вызова, эффективно выделяя в стеке.

У этого есть интересный побочный эффект создания связанных списков, которые больше не кэшируют враждебные (поскольку связанные с обратным вызовом списки, выделенные в стеке, все будут находиться рядом друг с другом в стеке, что позволяет делать такие вещи, как манипуляции с runtime string без каких-либо mallocs, и позволяет вам создавать неизвестные пользовательские входы без каких-либо mallocs.

Ответ 6

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

Ответ 7

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

вы также можете захотеть убедиться, что индексы, которые вы устанавливаете, действительно существуют в вашем массиве, как я отметил выше

Ответ 8

Во-первых, если у вас нет C99, у которого VLA s, размер массива должен быть постоянным на C. Вы не можете использовать инструкцию ниже

int factorFunction[size];

Во-вторых, вы пытаетесь вернуть массив, созданный в функции, которая будет удалена из области.

Чтобы этого избежать, вы можете взять массив как параметр в тестовой функции или динамически создать массив с помощью функции malloc. Btw ваша функция test может возвращать указатель на обновленный массив.

Ответ 9

Мое предложение состояло в том, чтобы передать массив, чтобы заполнить:

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], выходит за пределы массива.

Ответ 10

Вот еще один способ передать массив:

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

Статичность указывает, что переменная будет распределена таким образом, чтобы она оставалась в памяти. Поэтому, если у вас есть фиксированный размер для значения и вы хотите, чтобы он оставался в памяти между вызовами функций, это один из способов сделать это.

Ответ 11

Во-первых, вы не можете вернуть массив из функции в C напрямую. Что вы можете сделать, так это то, что вы можете вернуть адрес массива в эту функцию. В этом случае функция будет выглядеть примерно так:

int* test(int size, int x){

    /* function body */

    return factorFunction;
}

А для получения массива вам понадобится указатель - не массив.

Итак, вместо int factors[2]; вы должны использовать int *factors; в своей функции main.

Во-вторых, даже если вы вернете адрес массива, этот код не будет работать; потому что вы пытаетесь вернуть адрес локального массива; который не будет существовать после выполнения функции. Один простой способ решить эту проблему - объявить локальный массив (factorFunction в этом случае) static.

Учитывая эти два вопроса, функция test будет выглядеть так:

int* test(int size, int x){

    static int factorFunction[size];

    /* function body */

    return factorFunction;
}

Ответ 12

Очень простое объяснение кода о том, как вернуть массив обратно из пользовательской функции в основную функцию, надеюсь, это поможет. Ниже я написал полный код, чтобы сделать. простите за язык 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 why it is able to print the array:contiguous memory locations.
    }       
    return 0;//nothing to return that why 0
}