If I understand that you want to handle changing the storage for an array of pointers currently with static storage (on the stack in common terms) to a newly allocated block of memory, then you need to consider whether you simply want to change the storage of the pointers (referred to at times as a shallow copy) or whether you want to change the storage of both the pointers as well as the data pointed to (a deep copy).
While this is impossible to accomplish without passing more information to your stackTheap
function, if you provide it with the number of pointers you are dealing with, and the size of the data type pointed to, you can accomplish either a shallow or deep copy depending on what you pass to stackTheap
.
The following is just one example to approach a function that will either perform a shallow copy (if dsz
is 0
), or a deep copy if dsz
is passed a value. (there are many ways to pass various flags and parameters to accomplish this, this is just one approach)
Below, the example shows a shallow copy of parr
(pointer array) to narr
(new array). It then provides an example of a deep copy from parr
to narr2
with intermediate type pruning to char
using the same function. I'm not certain this is exactly what you are looking for, but if so and you have questions, just let me know:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 10
/* void copy array 'arr' of type 'sz' to 'arr_new'. if 'arr' is a
* pointer to an array of pointers to type 'dsz', a deep copy is
* required to copy contents pointed to by each of the array of
* pointers to a newly allocate block of memory.
* For a shallow copy, 'dsz = 0'.
*/
void *stackTheap (void *arr, size_t n, size_t sz, size_t dsz)
{
if (!arr) return NULL;
void* arr_new = malloc (n * sz);
memcpy (arr_new, arr, n * sz);
if (dsz) {
size_t i;
for (i = 0; i < n; i++) {
char **a = (char **)arr;
char **n = (char **)arr_new;
n[i] = malloc (dsz);
memcpy (n[i], a[i], dsz);
}
}
return arr_new;
}
int main (void) {
void *parr[MAXI] = {NULL}; /* void pointer array */
void **narr = {NULL}; /* new array (shallow copy) */
void **narr2 = {NULL}; /* new array (deep copy) */
int arr[MAXI] = {10,20,30,40,50,60,70,80,90,100}; /* array */
int i;
/* assigned pointers */
for (i = 0; i < MAXI; i++)
parr[i] = &arr[i];
/* print addressess of pointers and data on stack */
printf ("\n pointers stored on the stack\n");
for (i = 0; i < MAXI; i++)
printf (" parr[%2d] : %3d %p -> %p\n", i, *(int *)parr[i],
&parr[i], parr[i]);
/* shallow copy 'parr' to 'narr' */
narr = stackTheap (parr, MAXI, sizeof (int*), 0);
/* print address of pointers on heap data on stack */
printf ("\n pointers allocated on the heap\n"
" (pointing to original values on stack)\n");
for (i = 0; i < MAXI; i++)
printf (" narr[%2d] : %3d %p -> %p\n", i, *(int *)narr[i],
&narr[i], narr[i]);
/* deep copy 'parr' to 'narr2' */
narr2 = stackTheap (parr, MAXI, sizeof (int*), sizeof (int));
/* print addresses of pointers and data on heap */
printf ("\n pointers and data allocated on the heap\n");
for (i = 0; i < MAXI; i++)
printf (" narr2[%2d] : %3d %p -> %p\n", i, *(int *)narr2[i],
&narr2[i], narr2[i]);
/* free memory here */
free (narr);
for (i = 0; i < MAXI; i++)
free (narr2[i]);
free (narr2);
return 0;
}
Output
$ ./bin/void_pcpy
pointers stored on the stack
parr[ 0] : 10 0x7fff101e1a90 -> 0x7fff101e1a60
parr[ 1] : 20 0x7fff101e1a98 -> 0x7fff101e1a64
parr[ 2] : 30 0x7fff101e1aa0 -> 0x7fff101e1a68
parr[ 3] : 40 0x7fff101e1aa8 -> 0x7fff101e1a6c
parr[ 4] : 50 0x7fff101e1ab0 -> 0x7fff101e1a70
parr[ 5] : 60 0x7fff101e1ab8 -> 0x7fff101e1a74
parr[ 6] : 70 0x7fff101e1ac0 -> 0x7fff101e1a78
parr[ 7] : 80 0x7fff101e1ac8 -> 0x7fff101e1a7c
parr[ 8] : 90 0x7fff101e1ad0 -> 0x7fff101e1a80
parr[ 9] : 100 0x7fff101e1ad8 -> 0x7fff101e1a84
pointers allocated on the heap
(pointing to original values on stack)
narr[ 0] : 10 0x1e00010 -> 0x7fff101e1a60
narr[ 1] : 20 0x1e00018 -> 0x7fff101e1a64
narr[ 2] : 30 0x1e00020 -> 0x7fff101e1a68
narr[ 3] : 40 0x1e00028 -> 0x7fff101e1a6c
narr[ 4] : 50 0x1e00030 -> 0x7fff101e1a70
narr[ 5] : 60 0x1e00038 -> 0x7fff101e1a74
narr[ 6] : 70 0x1e00040 -> 0x7fff101e1a78
narr[ 7] : 80 0x1e00048 -> 0x7fff101e1a7c
narr[ 8] : 90 0x1e00050 -> 0x7fff101e1a80
narr[ 9] : 100 0x1e00058 -> 0x7fff101e1a84
pointers and data allocated on the heap
narr2[ 0] : 10 0x1e00070 -> 0x1e000d0
narr2[ 1] : 20 0x1e00078 -> 0x1e000f0
narr2[ 2] : 30 0x1e00080 -> 0x1e00110
narr2[ 3] : 40 0x1e00088 -> 0x1e00130
narr2[ 4] : 50 0x1e00090 -> 0x1e00150
narr2[ 5] : 60 0x1e00098 -> 0x1e00170
narr2[ 6] : 70 0x1e000a0 -> 0x1e00190
narr2[ 7] : 80 0x1e000a8 -> 0x1e001b0
narr2[ 8] : 90 0x1e000b0 -> 0x1e001d0
narr2[ 9] : 100 0x1e000b8 -> 0x1e001f0
Memory Check
$ valgrind ./bin/void_pcpy
==18688== Memcheck, a memory error detector
==18688== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==18688== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==18688== Command: ./bin/void_pcpy
==18688==
<snip>
==18688==
==18688== HEAP SUMMARY:
==18688== in use at exit: 0 bytes in 0 blocks
==18688== total heap usage: 12 allocs, 12 frees, 200 bytes allocated
==18688==
==18688== All heap blocks were freed -- no leaks are possible
==18688==
==18688== For counts of detected and suppressed errors, rerun with: -v
==18688== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)