如何在C中使用单个malloc分配三角形数组?

时间:2017-05-25 19:21:16

标签: c arrays malloc

我正在尝试使用单个malloc分配三角形数组,但我无法找到任何解决方案。我的结构是这样的:

          a  -  -  -  - 
          b  c  -  -  -  
          d  e  f  -  -  
          g  h  i  j  -
          k  l  m  n  o

我使用了两个malloc。

2 个答案:

答案 0 :(得分:4)

您打算如何使用该结构 - 您将编写什么代码来访问数组元素?另外,你要处理的数组大小是多少?

如果数组足够小(比如小于100x100,但边界值可以协商)那么使用常规矩形数组并像往常一样访问它,接受一些分配的空间未被使用是有意义的。如果阵列足够大以至于未使用的空间有问题,那么你必须更加努力。

您打算使用lt_matrix[r][c]表示法,还是使用从lt_matrix[x]x计算r的一维数组c?如果您可以使用1D表示法,则可以使用单个分配 - 如下面的代码中的技术1所示。如果使用双下标表示法,则应该进行两次内存分配 - 如下面的代码中的技术2所示。如果您不介意危险地生活,可以将技术3混合起来,但不建议您使用它,除非您可以确定限制和问题是什么,并自己评估它是否足够安全使用。 (如果你问我,答案是“不;不要使用它”,但这可能被认为过于谨慎。)

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

static inline int lt_index(int r, int c) { assert(r >= c); return r * (r + 1) / 2 + c; }

int main(void)
{
    int matrixsize = 5;

    /* Technique 1 */
    char *lt_matrix1 = malloc(matrixsize * (matrixsize + 1) / 2 * sizeof(*lt_matrix1));
    assert(lt_matrix1 != 0);  // Appalling error checking

    char value = 'a';
    for (int i = 0; i < matrixsize; i++)
    {
        for (int j = 0; j <= i; j++)
            lt_matrix1[lt_index(i, j)] = value++;
    }

    for (int i = 0; i < matrixsize; i++)
    {
        int j;
        for (j = 0; j <= i; j++)
            printf("%-3c", lt_matrix1[lt_index(i, j)]);
        for (; j < matrixsize; j++)
            printf("%-3c", '-');
        putchar('\n');
    }

    free(lt_matrix1);

    /* Technique 2 */
    char **lt_matrix2 = malloc(matrixsize * sizeof(*lt_matrix2));
    assert(lt_matrix2 != 0);  // Appalling error checking
    char *lt_data2 = malloc(matrixsize * (matrixsize + 1) / 2 * sizeof(*lt_matrix1));
    assert(lt_data2 != 0);  // Appalling error checking
    for (int i = 0; i < matrixsize; i++)
        lt_matrix2[i] = &lt_data2[lt_index(i, 0)];

    value = 'A';
    for (int i = 0; i < matrixsize; i++)
    {
        for (int j = 0; j <= i; j++)
            lt_matrix2[i][j] = value++;
    }

    for (int i = 0; i < matrixsize; i++)
    {
        int j;
        for (j = 0; j <= i; j++)
            printf("%-3c", lt_matrix2[i][j]);
        for (; j < matrixsize; j++)
            printf("%-3c", '-');
        putchar('\n');
    }

    free(lt_data2);
    free(lt_matrix2);

    /* Technique 3 - do not use this */
    void *lt_data3 = malloc(matrixsize * sizeof(int *) + matrixsize * (matrixsize + 1) / 2 * sizeof(int));
    assert(lt_data3 != 0);  // Appalling error checking
    int **lt_matrix3 = lt_data3;
    int *lt_base3 = (int *)((char *)lt_data3 + matrixsize * sizeof(int *));
    for (int i = 0; i < matrixsize; i++)
        lt_matrix3[i] = &lt_base3[lt_index(i, 0)];

    value = 1;
    for (int i = 0; i < matrixsize; i++)
    {
        for (int j = 0; j <= i; j++)
            lt_matrix3[i][j] = value++;
    }

    for (int i = 0; i < matrixsize; i++)
    {
        int j;
        for (j = 0; j <= i; j++)
            printf("%-3d", lt_matrix3[i][j]);
        for (; j < matrixsize; j++)
            printf("%-3c", '-');
        putchar('\n');
    }

    free(lt_data3);

    return 0;
}

该计划的输出是:

a  -  -  -  -  
b  c  -  -  -  
d  e  f  -  -  
g  h  i  j  -  
k  l  m  n  o  
A  -  -  -  -  
B  C  -  -  -  
D  E  F  -  -  
G  H  I  J  -  
K  L  M  N  O  
1  -  -  -  -  
2  3  -  -  -  
4  5  6  -  -  
7  8  9  10 -  
11 12 13 14 15 

Valgrind 3.13.0.SVN版(修订版16398)使用GCC 7.1.0在macOS Sierra 10.12.5上给出了一个干净的健康状况。

答案 1 :(得分:1)

如果要使用一个malloc并创建一个连续数组,则可以malloc(width * height * sizeof(Object))。如果要访问(x,y)位置,请使用:array[y * width + x]

使用两个malloc只会创建一个指针数组,这与一个像2D数组一样的连续数组略有不同。