通用二维数组

时间:2014-11-30 14:08:42

标签: c

我想像这样创建一个二维数组:

void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
    int i;
    void **m = malloc(nrLini * 4);
    if(m==NULL)
        return NULL;
    for(i=0; i<nrLini; i++)
    {
        *(m + (i*4)) = malloc(nrColoane * sizeOfElement);
        if(*(m + (i*4)) == NULL)
             return NULL;
    }
    return m;
}

我想这样用:

int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));

但它不起作用。我做错了什么?

5 个答案:

答案 0 :(得分:5)

您应该使用m[i]而不是*(m+i*4)并让编译器执行算术。

此外,如果发生故障,您应该释放已经分配的内存。

请改为尝试:

void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
    int i;
    void **m = malloc(nrLini * sizeof(void*));
    if (m == NULL)
        return NULL;
    for (i=0; i<nrLini; i++)
    {
        m[i] = malloc(nrColoane * sizeOfElement);
        if (m[i] == NULL)
        {
             while (i-- > 0)
                 free(m[i]);
             free(m);
             return NULL;
        }
    }
    return m;
}

答案 1 :(得分:4)

[不是问题的答案,而是其他人给出的正确答案的缩进用法]

void数组的形式访问int指针数组,执行此操作

int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));

不正确,根据C标准,只有void*正确转换为任何其他指针,void**并非必需。所以它应该正确

void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv;  /* Please note, there is NO casting necessary here! */

然后像这样访问成员:

pi[0] = 42  
pi[1] = 43; 
...

这与做

相同
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;

这确实没有意义,因为pi已经是int*,因此完全正确的方法(也考虑到第二维)将是:

((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;

可以通过定义宏来使其可用:

#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
  ((type *)(address[r]))[c] 

GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;

答案 2 :(得分:3)

我将解决分配一个void指针数组然后将它们解释为int指针数组的问题。

int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));

即使假设分配完全正确,nope的赋值和后来的使用也是未定义的行为。 void**int**具有不兼容的类型。

您可以做的是以下内容。将void指针逐个分配给int指针数组。

void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
    arr[i] = arrp[i] ;

然后使用arr数组,当你想释放内存时,释放原始指针:

free( arrp ) ;

答案 3 :(得分:2)

问题出现在这一行:

*(m + (i*4)) = malloc(nrColoane * sizeOfElement);

您必须知道,在向地址添加号码时,地址将以的数量递增,地址所指向的对象的大小。因此,如果您的指针指向大小为4个字节的对象,并且向其添加1,则地址将自动增加4,增加1.因此您应该放弃{{1 }}

此外,在分配空间时使用*4运算符,因为地址(以及指针)在不同的处理器体系结构上可以有不同的大小。

答案 4 :(得分:2)

实际上,如果你知道C99强大的VLA功能,你甚至不需要你的通用2D阵列功能。要分配真正的2D数组(不需要索引数组),只需执行以下操作:

int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));

那就是它。访问同样简单:

twoDIntArray[line][column] = 42;

在此代码中,twoDIntArray是指向width整数数组的指针。 malloc()调用只为height这样的行数组分配足够的空间。当您执行指针算术twoDIntArray[line]时,将line行数组的大小添加到指针,这将生成相应行数组的地址。然后,该行数组由第二个数组下标[column]索引。

毋庸置疑,释放这样一个阵列同样重要:

free(twoDIntArray);