C中二维数组的动态内存分配

时间:2017-02-18 02:35:40

标签: c arrays dynamic

我正在阅读关于2D数组的动态内存分配,我正在看这个例子:

int nrows = 2;
int ncols = 5;

char **pvowels = malloc(nrows * sizeof(char));

pvowels[0] = malloc(ncols * sizeof(char));
pvowels[1] = malloc(ncols * sizeof(char));

我的理解是第二个和第三个malloc都分配了5个字符和pvowels [0]以及pvowels [1]指向每个内存的大小,但是我无法理解第一个malloc。

第一个malloc看起来像是分配2个字符大小的内存,并使用它来存储两个指针。但是不是char只有256个可能的值,指针可以达到数十亿?因此,如果它为存储指针分配内存,是不是需要比字符大?

4 个答案:

答案 0 :(得分:4)

首先,您的第一个malloc()不正确。使用nrows * sizeof(char)仅分配2个字节,而您需要2行char*个指针。你必须这样分配:

char **pvowels = malloc(nrows * sizeof(char*));

或者:

char **pvowels = malloc(nrows * sizeof(*pvowels));

另请注意,char **pvowels 是一个2D数组,而只是指向char指针的指针。如果您使用的是二维数组,例如char pvowels[][],则不需要在堆上动态分配指针。你也可以只为你的问题使用2D数组,例如char pvowels[2][5]ncolsnrows似乎在这种情况下是固定的。

其次,您对pvowels[0]pvowels[1]的分配只会为4个有效字符留出空间,例如"abcd",因为空终止字符{{1}需要1个空格}。你应该写:

\0

注意: pvowels[0] = malloc(ncols+1); /* +1 for '\0' */ pvowels[1] = malloc(ncols+1); 始终为1,因此不需要包含它。您还应该检查sizeof(char)是否已返回malloc()

答案 1 :(得分:2)

分配nrows指向char的{​​{1}}指针,然后单独分配nrows ncols char个数组,这样做有一个缺点,那就是单独的内存分配不保证在内存中是连续的。这种分裂会导致性能下降。

更好的方法是分配足够的内存来容纳2d数组,并将结果指针指向指向ncols char s数组的指针。如图所示,这种方法确实依赖于VLA,但是自C99以来这些已成为C的一部分。这样做的好处是可以一次分配内存,只需要一次分配即可。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    size_t nrows = 2;
    size_t ncols = 5;

    /* Allocate space for a 2d array */
    char (*pvowels)[ncols] = malloc(sizeof (char[nrows][ncols]));

    /* Another alternative */
//    char (*pvowels)[ncols] = malloc(nrows * ncols);

    if (pvowels == NULL) {
        fprintf(stderr, "Unable to allocate memory\n");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < nrows; i++) {
        for (size_t j = 0; j < ncols; j++) {
            pvowels[i][j] = 'a' + i * ncols + j;
        }
    }

    for (size_t i = 0; i < nrows; i++) {
        for (size_t j = 0; j < ncols; j++) {
            printf("%5c", pvowels[i][j]);
        }
        putchar('\n');
    }

    free(pvowels);

    return 0;
}

节目输出:

a    b    c    d    e
f    g    h    i    j

答案 2 :(得分:1)

char ** pvowels是一个指向指针的指针,这意味着它的行为就像一个声明如下的数组: char * pvowels [数字]; 所以基本上,在你提供的例子中,指向了chars而不是指针。

答案 3 :(得分:0)

简单易懂的代码:(仅使用一个指针来存储和访问)

#include<stdio.h>
#include<stdlib.h>
int main(){
    int *a,n,r,c,i,j;
    scanf("%d",&n);
    r=c=n;
    a=(int *)malloc(r*c*sizeof(int));
    for(i=0;i<r;i++)
    {
        for(j=0;j<c;j++){
            scanf("%d",(a+i*c+j));
        }
    }
    for(i=0;i<r;i++)
    {
        for(j=0;j<c;j++){
            printf("%d",*(a+i*c+j));
        }
    }
}

参考文献:geeksforgeeks.org