Функция всегда возвращает указатель на ноль - PullRequest
0 голосов
/ 22 октября 2018

Почему функция createArray возвращает указатель на 0?Я думаю, что я должен использовать malloc, чтобы исправить это, но почему?

   int *createArray(int size)
{
    int i;
    int arr[size];

    i = 0;
    while (i < size)
    {
        arr[i] = i;
        i++;
    }
    return arr;
}

int main()
{
    int *ar;
    printf("%i", (createArray(10)));
}

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

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

Итак, вы возвращаете указатель на переменную, которой больше не существует.Любое использование этого указателя вызывает неопределенное поведение .В этом конкретном случае неверный адрес может быть разыменован и может содержать значение 0, однако нет никакой гарантии, что поведение будет согласованным при внесении изменений в вашу программу.

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

int *arr = malloc(sizeof(*arr) * size);

Это также означает, что вам понадобится free эта память, когда вы закончите использовать ее:

int *ar = createArray(10);
printf("%i", ar[0]);
free(ar);
0 голосов
/ 22 октября 2018

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

Чтобы исправить некоторые проблемы с вашим кодом, я добавил #include <stdio.h> в начало (требуется для printf)и изменил ваш printf вызов с

printf("%i", (createArray(10)));

на

printf("%p\n", (void*)createArray(10));

Когда я компилирую с помощью gcc и запускаю программу, вывод:

(nil)

Это означает, что ваша функция возвращает нулевой указатель.(Это не «указатель на ноль»; указатель равен ноль.) Это не то, что я ожидал;Я ожидал неверное значение указателя мусора.(Когда я использую tcc вместо gcc, я получаю 0x7fffd95a7140.)

Очевидно, что gcc распознает, что ваш код имеет неопределенное поведение, и заменяет оператор return эквивалентом return NULL;.Это совершенно законное преобразование (и оно может помешать вашей программе делать что-то неприятное с недействительным указателем, изменяя память, которой ваша программа не владеет).

Итог: ваша программа имеет неопределенное поведение, и выне могу предположить, что он будет делать.И да, выделение массива с использованием malloc и возврат адреса выделенного массива - один из способов исправить это.

0 голосов
/ 22 октября 2018

переменная arr размещена в стеке.При возврате из вашей функции стек освобождается.Указатель, который вы возвращаете, будет затем указывать на недопустимую ячейку памяти, которая может быть установлена ​​в нуль.

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