Преобразовать список в массив - PullRequest
1 голос
/ 18 августа 2010

У меня есть функция, которая преобразует список в массиве:

void* list_to_array(SList* list)
{
     int i;
     int array_size = list_get_length(list);

     void* array[array_size];

     for (i = 0; i < array_size; i++)
     {
      array[i] = list_get_n_data(list,i);
     }

     return *array;
}

Но когда я пытаюсь это проверить:

int* a = (int*)list_to_array(list);
printf("%d" (int)a);

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

int* a = (int*)list_to_array(list);
a++;
printf("%d" (int)a);

я вижу первый элемент + 4. Если я пытаюсь получить третий элемент, я вижу значение первого элемента + 8 и т. Д. ... Почему?Что не так?

Спасибо

Ответы [ 4 ]

6 голосов
/ 18 августа 2010

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

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

int array[] {1, 2, 3, 4};
return *array

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

void** array = (void **) malloc(sizeof(void *) * array_size); 
...
return array;

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

void **array = list_to_array(list);
// Use array
...
// Finished with array
free(array);
1 голос
/ 18 августа 2010

Если вы увеличите указатель int* a на 1, он будет фактически увеличен на sizeof(int), что, как минимум, в большинстве систем, 4.

Так что если

int* a = 0x40b8c438

тогда

a + 1
      = ((void*) a) + sizeof(int)
      = 0x40b8c43c

и

a + 2
      = ((void*) a) + sizeof(int) * 2
      = 0x40b8c440
0 голосов
/ 15 февраля 2018

Вы должны быть осторожны с указателями, объявите это так:

int main()
{
    int *array;
    int i;
    i = size(list);
    array = list_to_array(list, i);

...
free(array);
}

int     size(t_list *list)
{
    int i;

    i = 0;
    while (list)
    {
        i++;
        list = list->next;
    }
    return (i);
}

int     *list_to_array(t_list *list, int size)
{
    int     *array;
    int     i;
    t_list  *temp;

    i = 0;
     if (list == NULL)
        return (NULL);
    array = (int*)malloc(sizeof(int) * size + 1);
    temp = list;
    while (temp)
    {
        array[i] = temp->data;
        temp = temp->next;
        i++;
    }
    return (array);
}
0 голосов
/ 18 августа 2010

У вас есть три проблемы здесь.Первый тривиален, вы возвращаете первый элемент массива с return *array, когда вы имеете в виду возвращать указатель на первый элемент массива с return array.НЕ ОСТАНАВЛИВАЙТЕСЬ ЗДЕСЬ!Во-вторых, вы увеличиваете указатель на 1, а не на размер данных, на которые вы указываете.Это приведет к неправильным результатам.Третья проблема гораздо серьезнее:
Вы выделяете память для вашего массива в этой строке:

void* array[array_size];

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

int* a = (int*)list_to_array(list);

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

int* a = (int*)list_to_array(list1);
int* b = (int*)list_to_array(list2);
printf("%d" (int)a);

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

Вы должны выделить вашу память с той же областью, что и.

// Prototype
void* list_to_array(SList* list, void* dest_array); 

// C99 (Or use malloc)
void* array[list_get_length(list)];                 

int* a = (int*)list_to_array(list, array);  
other_functions();    
// Works every time!
printf("%d" (int)a);       

Менее серьезная проблема заключается в том, что вы не увеличиваете указатель на правильную величину.Вам нужно использовать оператор sizeof ().Кроме того, вы можете получить доступ к элементам массива с помощью [].

int* a = (int*)list_to_array(list, array);  
printf("%d" a[1]);    //Prints second element of a
a += sizeof(int) * 2;
printf("%d" (int)a);  //Prints third element of a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...