Статический или указатель при возвращении массива - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь загрузить массив размером n (пользовательский ввод) со случайными значениями.Я читал, что вы не можете вернуть массив в C, вы должны использовать указатель (что довольно запутанно).Тем не менее, я прочитал, что если вы сохраняете этот массив в локальной переменной в возвращаемой функции, указатель не будет работать, и статический массив может быть использован (может ли он быть возвращен в функции?).Кроме того, я читал, что вы должны вызывать free после того, как использование массива откроет пространство обратно?Я должен использовать это неправильно, потому что он разбился.Так что я закомментировал это сейчас.Некоторое разъяснение было бы здорово.

Вот то, что я имею до сих пор.При печати он просто печатает то, что я считаю просто мусором.

int* prefixAverages1(int);

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main() {

    int choice;
    int input;

    printf("What is the size of the array?:");
    scanf("%d", &input);
    printf("Do you want to run prefixAverages 1 or 2?");
    scanf("%d", &choice);

    switch(choice) {
        case 1:
            printf("Beginning prefixAverages1\n");
            int *a = prefixAverages1(input);
            for (int i=0; i < input; i++) {
                printf("%d", &i);
                printf("%d \n", a[i]);
            }
            //free(a);
            break;
    }
}

int* prefixAverages1(int input) {
    int x[input];
    int *a = (int*)malloc(input);
    srand(time(NULL));  

    for(int i = 0; i < input; i++) {
        int s = 0;
        for(int j = 0; j < i; j++) {
            int r = rand() % 100;
            x[j] = r;
            s = s + x[j];
        }
        a[i] = s / (i+1);
        printf("%d \n", a[i]);
    }
    return a;
}

Я знаю, что мой синтаксис может быть некорректным.Я не прикасался к С несколько лет, поэтому дайте мне знать, если моя ошибка синтаксическая.

edit: значения печатаются так, как задумано в функции.Добавлен оператор печати в коде для ясности

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Это работает, если имеется функция, которая загружает массив со случайными значениями:

void randomValues(int arr[], int size);

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main() {
    int i;
    int input;
    int *array;

    printf("What is the size of the array?: ");
    scanf("%d", &input);

    array = malloc(sizeof(int) * input);

    randomValues(array, input);

    for(i = 0; i < input; ++i)
        printf("array[%d] = %d\n", i, array[i]);

    free(array);

    return 0;
}

void randomValues(int arr[], int size) {
    int i;
    int r;

    srand((int) time(0));

    for(i = 0; i < size; ++i) {
        r = rand() % 100;
        arr[i] = r;
    }
}
0 голосов
/ 22 мая 2018

Я пытаюсь загрузить массив размером n (пользовательский ввод) со случайными значениями.Я читал, что вы не можете вернуть массив в C, вы должны использовать указатель (что весьма запутанно).

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

Но в некоторых местах это высовывается.Например, нет действительного синтаксиса, который позволяет вам даже пытаться объявить функцию, которая возвращает массив.

В других местах он активно вводит в заблуждение.Например, вы можете объявить функцию, которая появляется , чтобы принять массив в качестве аргумента, но стандарт явно указывает, что аргумент на самом деле является соответствующим указателем (и это то, что естественно выпадает, когда вы вызываете такую ​​функциютем не мение).В частности:

int foo(int x[3]);

на 100% эквивалентно

int foo(int *x);

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

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

и статический массив можно использовать (может ли он быть возвращен в функции?).

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

Кроме того, я прочитал, что после использования вы должны вызывать freeмассив открыт, пространство резервной копии?

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

На самом деле, большинство из того, что вы демонстрируете в своем примере кода, в порядке.в этом отношении.Однако вы делаете ключевую ошибку, которая подрывает вашу программу.Здесь:

    int *a = (int*)malloc(input);

Вы выделяете input байт и сохраняете указатель на них в a, но этого недостаточно для inputобъекты типа int.Размер int варьируется от реализации к реализации, но минимальный размер, разрешенный стандартом, составляет два байта, в наиболее распространенном размере - четыре байта.Чтобы выделить место для input объектов типа int, основной идиомой является

int *a = malloc(input * sizeof(int));

Лично я предпочитаю

int *a = malloc(input * sizeof(*a));

, потому что тогда я получу правильный размер noНеважно, к какому типу относится ссылочный тип указателя, и даже если я изменю его позже.

Тот факт, что вы обработали выделенное пространство так, как если бы оно было больше, чем на самом деле, вероятно, объясняет большую часть неправильного поведения вашей программы, включаясбой при попытке освободить выделенную память.

0 голосов
/ 22 мая 2018

Прежде всего malloc принимает число байтов, а не абсолютный размер массива, поэтому измените эту строку: -

int *a = (int*)malloc(input);

на

int *a = malloc(input*sizeof(int));

Во-вторых, для отладкипри печати неверных значений поместите печать в вашу функцию prefixAverages1: -

...
...
a[i] = s / (i+1);
printf("%d \n", a[i]);
...

В основном шрифте избавьтесь от первого отпечатка .. это, вероятно, заставляет вас думать, что вы печатаете неправильные значения .. Адреспеременная локального счетчика цикла будет выглядеть как мусор

printf("%d", &i);

ИЛИ, если вы хотите отслеживать индексы элементов массива, также измените его на: -

printf("%d", i);

Вы должны ввестиfree назад, чтобы избежать утечки памяти

И вы должны следовать предложению @ AustinStephens и избегать использования второй функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...