指针指向 Void 的内存分配

Memory Allocation With Pointer to Pointer to Void

假设我有一个包含 void ** 成员的结构。该成员用作指向数据通道的指针数组。数据类型无关紧要。下面是我想如何为这个二维数组分配内存然后将通道指针与其内存相关联的示例。

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

所以,问题来了:这个取消引用和分配的行为是否如我所假设的那样?

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

也就是说,这个分​​配是否与我以后访问内存的方式兼容?

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

C 不支持在运行时发现数据类型的能力。如果您希望它与通用数据类型一起使用,您将必须传入一个变量,该变量定义您将要使用的数据类型的字节数。

我觉得你的总体思路还不错,但 (void **) malloc(sizeof(DATA_TYPE *) * N_CHANNELS) 让我的蜘蛛感觉刺痛。您为指向 DATA_TYPEN_CHANNELS 指针数组分配 space,但将其视为指向 void 的指针数组。 C 中没有任何东西可以保证 void *DATA_TYPE * 具有相同的大小和表示(除非 DATA_TYPE 恰好是 char)。因此,当将 ppdata[0] = ... 视为 DATA_TYPE * 的位时,您随后对 ppdata[0] = ... 的分配可能会产生垃圾(这是您稍后通过 ptr 所做的)。

我更喜欢这样:

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

之后您可以通过以下方式恢复您的指针数组:

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

从技术上讲,您不需要单独的指针数组,因为您有一个很好的矩形数组。你可以这样做:

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

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

之后:

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

即只需从 ij.

手动计算索引