Memory Allocation With Pointer to Pointer to Void

Let's assume that I have a struct with a void ** member. This member serves as an array of pointers to data channels. The data type is irrelevant. Below is an example of how I'd like to allocate memory for this 2D array and then associate channel pointers with their memory.

#define N_CHANNELS (/*Number of data channels*/)
#define N_SAMPLES (/*Number of data samples per channel*/)
typedef /*Some data type*/ DATA_TYPE;

void **ppdata; /*Conceptual struct member*/

/*Allocate memory for array of data channels */
ppdata = (void **) malloc(sizeof(DATA_TYPE *) * N_CHANNELS);
ppdata[0] = malloc(sizeof(DATA_TYPE) * N_CHANNELS * N_SAMPLES);

/*Cast for pointer arithmetic and data access*/
DATA_TYPE **ptr = (DATA_TYPE **) ppdata;

/*Associate channels with their memory*/
int alloc_index;
for (alloc_index = 0; alloc_index < N_CHANNELS; alloc_index++)
{
     ptr[alloc_index] = (*ptr + alloc_index * N_SAMPLES);
}

So, the question arises: Is this dereference and allocation behaving as I have assumed it is?

ppdata[0] = malloc(sizeof(DATA_TYPE) * N_CHANNELS * N_SAMPLES);

ie, is this allocation compatible with the manner in which I later access the memory?

DATA_TYPE **ptr = (DATA_TYPE **) ppdata;
...
ptr[alloc_index] = (*ptr + alloc_index * N_SAMPLES);

Your general idea looks OK to me, but (void **) malloc(sizeof(DATA_TYPE *) * N_CHANNELS) makes my spider-sense tingle. You allocate space for an array of N_CHANNELS pointers to DATA_TYPE , but treat it as an array of pointers to void . There's nothing in C that guarantees that a void * and a DATA_TYPE * have the same size and representation (unless DATA_TYPE happens to be char ). So your subsequent assignment to ppdata[0] = ... might produce garbage when looked at as the bits of a DATA_TYPE * (which is what you do later through ptr ).

I'd much prefer it this way:

/* overflow check omitted */
DATA_TYPE *storage = malloc(N_CHANNELS * N_SAMPLES * sizeof *storage);
/* error check omitted */

/* overflow check omitted */
DATA_TYPE **pointers = malloc(N_CHANNELS * sizeof *pointers);
/* error check omitted */

for (size_t i = 0; i < N_CHANNELS; i++) {
    pointers[i] = storage + i * N_SAMPLES;
}

/* struct member */
void *pdata = pointers;

Then later on you can recover your array of pointers by doing:

DATA_TYPE **pointers = pdata;
do_stuff_with(pointers[i][j]);

Technically you don't need a separate array of pointers, because you have a nice rectangular array. You could just do:

/* overflow check omitted */
DATA_TYPE *storage = malloc(N_CHANNELS * N_SAMPLES * sizeof *storage);
/* error check omitted */

/* struct member */
void *pdata = storage;

And later on:

DATA_TYPE *storage = pdata;
do_stuff_with(storage[i * N_SAMPLES + j]);

Ie just manually calculate the index from i and j .


C does not support the ability to discover datatype at runtime. You are going to have to pass in a variable that defines the number of bytes of the datatype you are going to be using if you want this to work with generic datatypes.

链接地址: http://www.djcxy.com/p/80230.html

上一篇: 直接Web Remoting问题

下一篇: 内存分配,指针指向无效