tags:

views:

80

answers:

3

Hello,

I have functon that convert list in array:

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;
}

But when i try to test it:

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

it's ok. I see first element. But when i try to get second or third element:

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

I see first element + 4. if i try get third element i see first element value + 8 and etc... Why? What's wrong?

Thank you

+6  A: 

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);
torak
He wrote: **return *array;** Maybe thats something valid? We won't know from his code.
rubber boots
Thank you for reply. How can i return array?
shk
+1 Allocating memory space with malloc() will ensure that your array continues to exist even after the function returns.
karlphillip
+1  A: 

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
Frxstrem
A: 

You have three problems here. The first is trivial, you're returning the first element of the array with return *array, when what you mean is to return a pointer to the first element of the array with return array. DON'T STOP HERE! The second is that you are incrementing your pointer by 1, rather than by the size of the data you're pointing to. This will cause you to get wrong results. The third problem is much more serious:
You allocate memory for your array on this line:

void* array[array_size];

This memory is allocated on the stack, and this memory is no longer allocated when you return from the function. When you later reference this memory with the line:

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

a is pointing to a region on the stack which is no longer in use. You get somewhat reasonable results with the code you have, but if you modify the stack after returning from your function, a will be pointing at the new memory. For example, if you use the following code:

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

You will (likely) see the first element of b. This is not guaranteed - You may also get a segmentation fault. Other code between the assignment to a and its use will also overwrite the contents of the memory you access in your printf statement.

You need to allocate your memory with the same scope as a.

// 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);       

The less serious problem is the fact that you're not incrementing your pointer by the correct amount. You need to use the sizeof() operator. Alternatively, you can access your array elements with [].

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
reemrevnivek