Как вы возвращаете указатель из функции за пределами main () - PullRequest
0 голосов
/ 01 декабря 2018

Мой вопрос о динамическом выделении памяти в C. Меня попросили динамически выделить массив длинных n и вернуть указатель на первый элемент этого массива.У меня есть некоторый код, чтобы проверить вывод этого, но распределение памяти не удается.

long* make_long_array(long n)
{
    int i;
    int *a;

    a = (int*)malloc(sizeof(int)*n);
    if (a == NULL) {
        printf("ERROR: Out of memory\n");
        return 1;
    }

    for (i = 0; i < n; *(a + i++) = 0);
    return *a;
}

Я получаю сообщение об ошибке в двух строках, говорящее:

'error: return делает указатель изцелое число без приведения '

это происходит для строк

return 1;

и

return *a;

Я не совсем уверен, как это исправить.Я думаю, что ошибка в return 1; в том, что я пытаюсь вернуть целое число, когда он ищет указатель?Но я не уверен, как это исправить для возврата указателя.Любая помощь будет высоко ценится.

1 Ответ

0 голосов
/ 01 декабря 2018

Чтобы исправить исходную версию:

long* make_long_array(/* long not the correct type for sizes of objects */ size_t n)
{
    // int i;  define variables where they're used.
    /* int you want to return a */ long *a; // array.

    a = /* (int*) no need to cast */ malloc(sizeof(/* int */ you want */ long /*s, remember? *) */ ) * n);
    if (a == NULL) {
        printf("ERROR: Out of memory\n");  // puts()/fputs() would be sufficient.
        return /* 1 */ NULL;  // 1 is an integer. Also it is uncommon to return
    }                         // anything other than NULL when a memory allocation
                              // fails.

    for (size_t i = 0; i < n; /* *(a + i++) = 0 that falls into the category obfuscation */ ++i )
        /* more readable: */ a[i] = 0;
    // return *a; you don't want to return the first long in the memory allocated
    return a; // but the address you got from malloc()
}

A Better Way tm для записи таких распределений составляет

FOO_TYPE *foo = malloc(NUM_ELEMENTS * sizeof(*foo)); // or
BAR_TYPE *bar = calloc(NUM_ELEMENTS, sizeof(*bar));

Используя *foo и *bar в качестве операнда sizeof, вам не нужно беспокоиться об изменении его при изменении типа foo или bar.

ВашФункция может быть упрощена до

#include <stddef.h>  // size_t
#include <stdlib.h>  // calloc()

long* make_long_array(size_t size)      // size_t is guaranteed to be big enough to hold
{                                       // all sizes of objects in memory and indexes
    return calloc(size, sizeof(long));  // into them. calloc() initializes the memory
}                                       // it allocates with zero.

// if you really want an error-message printed:

long* make_long_array(size_t size)
{
    long *data = calloc(size, sizeof(long));
    if (!data)  // calloc() returned NULL
        fputs("Out of memory :(\n\n", stderr);  // Error messages should go to stderr
    return data;                                // since it is unbuffered*) and
}                                               // might be redirected by the user.

*), поэтому пользователь мгновенно получает сообщение.

Также нет необходимости приводить результат к *alloc(), так как он возвращает void*который неявно конвертируется в любой другой тип указателя.

Может быть записан как макрос, поэтому он работает не только для long, но и для любого типа:

#include <stddef.h>
#include <stdlib.h>

#define MAKE_ARRAY(TYPE, COUNT) calloc((COUNT), sizeof((TYPE)))

// sample usage:

int main(void)
{
    int  *foo = MAKE_ARRAY(*foo, 12);
    long *bar = MAKE_ARRAY(*bar, 24);
    char *qux = MAKE_ARRAY(*qux, 8);

    free(qux);
    free(bar);
    free(foo);
}
...