假设我有一个带有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);
答案 0 :(得分:0)
C不支持在运行时发现数据类型的能力。如果希望使用通用数据类型,则必须传入一个变量来定义您将要使用的数据类型的字节数。
答案 1 :(得分:0)
你的一般想法对我来说很好,但(void **) malloc(sizeof(DATA_TYPE *) * N_CHANNELS)
使我的蜘蛛感觉刺痛。您为N_CHANNELS
的{{1}}指针数组分配空间,但将其视为指向DATA_TYPE
的指针数组。 C语言中没有任何内容可以保证void
和void *
具有相同的大小和表示形式(除非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
手动计算索引。