You are returning a pointer to a stack memory location. That memory region is no longer valid once the function returns.
Also, instead of actually returning a pointer to the array, you are returning the first element in the array. The following code will return 1, not a pointer the array.
int array[] {1, 2, 3, 4};
return *array
You probably only need to make minimal changes your code to get it to work.
void** array = (void **) malloc(sizeof(void *) * array_size);
...
return array;
Just make sure that you release the memory that memory used for array when you are finished with it.
void **array = list_to_array(list);
// Use array
...
// Finished with array
free(array);
Answer from torak on Stack OverflowYou are returning a pointer to a stack memory location. That memory region is no longer valid once the function returns.
Also, instead of actually returning a pointer to the array, you are returning the first element in the array. The following code will return 1, not a pointer the array.
int array[] {1, 2, 3, 4};
return *array
You probably only need to make minimal changes your code to get it to work.
void** array = (void **) malloc(sizeof(void *) * array_size);
...
return array;
Just make sure that you release the memory that memory used for array when you are finished with it.
void **array = list_to_array(list);
// Use array
...
// Finished with array
free(array);
When you increase the pointer int* a by 1, it would actually increase it by sizeof(int), which is - on most systems, at least - 4.
So if
int* a = 0x40b8c438
then
a + 1
= ((void*) a) + sizeof(int)
= 0x40b8c43c
and
a + 2
= ((void*) a) + sizeof(int) * 2
= 0x40b8c440
The last node of the list ends up with a NULL next and a garbled value. I don't think this is what you wanted. Try this loop:
struct List* head = NULL;
struct List** tail = &head;
for(int i = 0; i < length; i++) {
*tail = malloc(sizeof(struct List));
if (*tail == NULL) {
listDestroy(head, freeElement);
return NULL;
}
tail[0]->value = copyElement(array[i]);
tail = &(tail[0]->next);
}
*tail = NULL;
return head;
This uses a pointer to pointer so that we can update head or next depending on where we are in the loop without an extra if condition. Note that the allocaction of head is inside the loop now, so we always allocate exactly as many nodes as we need.
void* array[] is completely valid in this scenario, although I don't see the point of copyElement.
Perhaps just remove it and use array[i] instead?
I'd also like to point out a few mistakes that you may want to fix in your code:
Don't cast the result of malloc and use sizeof(*var) instead of sizeof(type). They're unneeded and may cause issues later on if you change the type of head. So, change this (and any later occurrences):
struct List* head = (struct List*) malloc(sizeof(struct List));
to this:
struct List* head = malloc(sizeof(*head));
Consider returning struct List * from arr2list. Change this:
void* arr2list(void* array[], int length, void* copyElement(void*), void freeElement(void*)) {
to this:
struct List* arr2list(void* array[], int length, void* copyElement(void*), void freeElement(void*)) {
Also, use either struct List * or List *. Inconsistencies may make it hard to understand your code.
It may be clearer if you pass function pointers to your functions instead of just functions. So, instead of doing this:
returntype func(params),
do this:
returntype (*func)(params),
You may also want to change malloc calls to calloc calls. calloc zeroes out memory, which can help in debugging. Change:
malloc(...)
to:
calloc(1, ...)
Here's an example combining code fixes from Joshua's post and mine:
list.c:
#include <stdlib.h>
typedef struct List {
struct List* next;
void *value;
} List;
void listDestroy(struct List* list, void (*freeElement)(void*)) {
while(list != NULL) {
freeElement(list->value);
struct List* temp_node = list;
list = list->next;
free(temp_node);
}
}
struct List* arr2list(void* array[], int length, void (*freeElement)(void*)) {
struct List* head = NULL;
struct List** tail = &head;
if (length == 0 || !freeElement) {
return NULL;
}
for(int i = 0; i < length; i++) {
*tail = calloc(1, sizeof(struct List));
if (*tail == NULL) {
listDestroy(head, freeElement);
return NULL;
}
tail[0]->value = array[i];
tail = &(tail[0]->next);
}
*tail = NULL;
return head;
}
test.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.c"
void free_element(void *el)
{
free(el);
}
int main(void)
{
List *list;
int ctr;
void *array[4];
for(ctr = 0; ctr < 4; ctr++)
{
/* Don't usually pass sizeof(type) to malloc(),
* but these are extenuating circumstances. */
array[ctr] = malloc(sizeof(int));
if(!array[ctr]) return 1;
*(int *)array[ctr] = ctr * 4;
}
list = arr2list(array, sizeof(array)/sizeof(array[0]), free_element);
while(list)
{
printf("%d\n", *(int *)list->value);
list = list->next;
}
listDestroy(list, free_element);
return 0;
}
Output:
0
4
8
12
One last note: you may consider creating a header file that defines these structures and functions (and remove the structure from list.c). Here's an example:
#ifndef LIST_H
#define LIST_H 1
typedef struct List { // Remove this from list.c
struct List* next;
void *value;
} List;
void listDestroy(struct List*, void (*)(void*));
struct List* arr2list(void* [], int, void (*)(void*));
#endif
c# - Conversion of System.Array to List - Stack Overflow
Need help with converting an array to a list in C#` - Questions & Answers - Unity Discussions
C# array to list
How to make a list
Save yourself some pain...
using System.Linq;
int[] ints = new [] { 10, 20, 10, 34, 113 };
List<int> lst = ints.OfType<int>().ToList(); // this isn't going to be fast.
Can also just...
List<int> lst = new List<int> { 10, 20, 10, 34, 113 };
or...
List<int> lst = new List<int>();
lst.Add(10);
lst.Add(20);
lst.Add(10);
lst.Add(34);
lst.Add(113);
or...
List<int> lst = new List<int>(new int[] { 10, 20, 10, 34, 113 });
or...
var lst = new List<int>();
lst.AddRange(new int[] { 10, 20, 10, 34, 113 });
There is also a constructor overload for List that will work... But I guess this would required a strong typed array.
//public List(IEnumerable<T> collection)
var intArray = new[] { 1, 2, 3, 4, 5 };
var list = new List<int>(intArray);
... for Array class
var intArray = Array.CreateInstance(typeof(int), 5);
for (int i = 0; i < 5; i++)
intArray.SetValue(i, i);
var list = new List<int>((int[])intArray);
I want to convert a bunch of inputs into a list.
a,b,c,d a,b,d,c a,c,b,d
Is there any way to make that as a list?
List<object> list = myArray.Cast<Object>().ToList();
If the type of the array elements is a reference type, you can leave out the .Cast<object>() since C#4 added interface co-variance i.e. an IEnumerable<SomeClass> can be treated as an IEnumerable<object>.
List<object> list = myArray.ToList<object>();
Use the constructor: new List<object>(myArray)