使用指向无效指针的内存分配

时间:2017-09-21 19:04:18

标签: c pointers memory memory-management void-pointers

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

你的一般想法对我来说很好,但(void **) malloc(sizeof(DATA_TYPE *) * N_CHANNELS)使我的蜘蛛感觉刺痛。您为N_CHANNELS的{​​{1}}指针数组分配空间,但将其视为指向DATA_TYPE的指针数组。 C语言中没有任何内容可以保证voidvoid *具有相同的大小和表示形式(除非DATA_TYPE *恰好是DATA_TYPE)。因此,对char的后续分配在查看ppdata[0] = ...的位时可能会产生垃圾(这是您稍后通过DATA_TYPE *执行的操作)。

我更喜欢这样:

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]); i手动计算索引。