C中动态分配数组的数组

发布于 2024-07-11 21:13:08 字数 301 浏览 8 评论 0原文

我并不真正理解 C 中的一些基本知识,例如动态分配数组的数组。 我知道你可以这样做:

int **m;

为了声明一个二维数组(随后将使用某些 *alloc 函数进行分配)。 此外,还可以通过执行 *(*(m + line) + column) 来“轻松”访问它。 但是我应该如何为该数组中的元素赋值呢? 使用 gcc,以下语句 m[line][column] = 12; 因分段错误而失败。

任何文章/文档将不胜感激。 :-)

I don't truly understand some basic things in C like dynamically allocating array of arrays.
I know you can do:

int **m;

in order to declare a 2 dimensional array (which subsequently would be allocated using some *alloc function). Also it can be "easily" accessed by doing *(*(m + line) + column). But how should I assign a value to an element from that array? Using gcc the following statement m[line][column] = 12; fails with a segmentation fault.

Any article/docs will be appreciated. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

离笑几人歌 2024-07-18 21:13:08

m[line][column] = 12 语法没问题(前提是 linecolumn 在范围内)。

但是,您没有编写用于分配它的代码,因此很难确定它是错误还是正确。 它应该是

m = (int**)malloc(nlines * sizeof(int*));

for(i = 0; i < nlines; i++)
  m[i] = (int*)malloc(ncolumns * sizeof(int));

一些旁注的内容:

  • 这样,您可以为每行分配不同的长度(例如三角形数组)
  • 您可以稍后在使用数组时对单独的行进行 realloc() 或 free()
  • 您当您 free() 整个数组时,必须 free() 每一行

The m[line][column] = 12 syntax is ok (provided line and column are in range).

However, you didn't write the code you use to allocate it, so it's hard to get whether it is wrong or right. It should be something along the lines of

m = (int**)malloc(nlines * sizeof(int*));

for(i = 0; i < nlines; i++)
  m[i] = (int*)malloc(ncolumns * sizeof(int));

Some side-notes:

  • This way, you can allocate each line with a different length (eg. a triangular array)
  • You can realloc() or free() an individual line later while using the array
  • You must free() every line, when you free() the entire array
梦幻的心爱 2024-07-18 21:13:08

您的语法 m[line][colummn] 是正确的。 但为了在 C 中使用二维数组,必须为其分配内存。 例如,此代码将为给定行和列的表分配内存。

int** AllocateArray(int line, int column) {
  int** pArray = (int**)malloc(line*sizeof(int*));
  for ( int i = 0; i < line; i++ ) {
    pArray[i] = (int*)malloc(column*sizeof(int));
  }
  return pArray;
}

请注意,为了简洁起见,我省略了 malloc 的错误检查。 真正的解决方案应该包括它们。

Your syntax m[line][colummn] is correct. But in order to use a 2D array in C, you must allocate memory for it. For instance this code will allocated memory for a table of given line and column.

int** AllocateArray(int line, int column) {
  int** pArray = (int**)malloc(line*sizeof(int*));
  for ( int i = 0; i < line; i++ ) {
    pArray[i] = (int*)malloc(column*sizeof(int));
  }
  return pArray;
}

Note, I left out the error checks for malloc for brevity. A real solution should include them.

温暖的光 2024-07-18 21:13:08

它不是一个二维数组 - 它是一个数组的数组 - 因此它需要多次分配。

It's not a 2d array - it's an array of arrays - thus it needs the multiple allocations.

中二柚 2024-07-18 21:13:08

这是 quinmars 解决方案的修改版本,它仅分配单个内存块,并且可以通过 void * 与通用值一起使用:

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

void ** array2d(size_t rows, size_t cols, size_t value_size)
{
    size_t index_size = sizeof(void *) * rows;
    size_t store_size = value_size * rows * cols;

    char * a = malloc(index_size + store_size);
    if(!a) return NULL;

    memset(a + index_size, 0, store_size);
    for(size_t i = 0; i < rows; ++i)
        ((void **)a)[i] = a + index_size + i * cols * value_size;

    return (void **)a;
}

int printf(const char *, ...);

int main()
{
    int ** a = (int **)array2d(5, 5, sizeof(int));
    assert(a);
    a[4][3] = 42;
    printf("%i\n", a[4][3]);
    free(a);
    return 0;
}

我不确定将 void ** 转换为 int 是否真的安全** (我认为标准允许在与 void * 进行转换时进行转换?),但它可以在 gcc 中工作。 为了安全起见,您应该将每次出现的 void * 替换为 int * ...


先前算法的类型安全版本:

#define alloc_array2d(TYPE, ROWS, COLS) \
    calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)

#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
    do { for(int i = 0; i < ROWS; ++i) \
        ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
        i * COLS * sizeof(TYPE)); } while(0)

以下宏实现了 他们像这样:

int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;

Here's a modified version of quinmars' solution which only allocates a single block of memory and can be used with generic values by courtesy of void *:

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

void ** array2d(size_t rows, size_t cols, size_t value_size)
{
    size_t index_size = sizeof(void *) * rows;
    size_t store_size = value_size * rows * cols;

    char * a = malloc(index_size + store_size);
    if(!a) return NULL;

    memset(a + index_size, 0, store_size);
    for(size_t i = 0; i < rows; ++i)
        ((void **)a)[i] = a + index_size + i * cols * value_size;

    return (void **)a;
}

int printf(const char *, ...);

int main()
{
    int ** a = (int **)array2d(5, 5, sizeof(int));
    assert(a);
    a[4][3] = 42;
    printf("%i\n", a[4][3]);
    free(a);
    return 0;
}

I'm not sure if it's really safe to cast void ** to int ** (I think the standard allows for conversions to take place when converting to/from void * ?), but it works in gcc. To be on the safe side, you should replace every occurence of void * with int * ...


The following macros implement a type-safe version of the previous algorithm:

#define alloc_array2d(TYPE, ROWS, COLS) \
    calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)

#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
    do { for(int i = 0; i < ROWS; ++i) \
        ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
        i * COLS * sizeof(TYPE)); } while(0)

Use them like this:

int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
嘦怹 2024-07-18 21:13:08

尽管我同意其他答案,但在大多数情况下最好立即分配整个数组,因为 malloc 非常慢。


int **
array_new(size_t rows, size_t cols)
{
    int **array2d, **end, **cur;
    int *array;

    cur = array2d = malloc(rows * sizeof(int *));
    if (!array2d)
        return NULL;

    array = malloc(rows * cols * sizeof(int));
    if (!array)
    {
        free(array2d);
        return NULL;
    }

    end = array2d + rows;
    while (cur != end)
    {
        *cur = array;
        array += cols;
        cur++;
    }

    return array2d;
}

要释放数组只需执行以下操作:
自由(*数组); 自由(数组);

注意:此解决方案仅在您不想更改行的顺序时才有效,因为您可能会丢失第一个元素的地址,稍后您需要释放该数组。

Although I agree with the other answers, it is in most cases better to allocate the whole array at once, because malloc is pretty slow.


int **
array_new(size_t rows, size_t cols)
{
    int **array2d, **end, **cur;
    int *array;

    cur = array2d = malloc(rows * sizeof(int *));
    if (!array2d)
        return NULL;

    array = malloc(rows * cols * sizeof(int));
    if (!array)
    {
        free(array2d);
        return NULL;
    }

    end = array2d + rows;
    while (cur != end)
    {
        *cur = array;
        array += cols;
        cur++;
    }

    return array2d;
}

To free the array simply do:
free(*array); free(array);

Note: this solution only works if you don't want to change the order of the rows, because you could then lose the address of the first element, which you need to free the array later.

凶凌 2024-07-18 21:13:08

嗯。 老式时尚烟雾和镜子作为一种选择怎么样?

#define ROWS  5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))

int main(void)
{
    int *p = (int *) malloc (ROWS * COLS * sizeof(int));
    if (p != NULL)
    {
        size_t r;
        size_t c;
        for (r = 0; r < ROWS; r++)
        {
            for (c = 0; c < COLS; c++)
            {
                 X(r,c) = r * c;  /* put some silly value in that position */ 
            }
        }

        /* Then show the contents of the array */ 
        for (r = 0; r < ROWS; r++)
        {
            printf("%d ", r);   /* Show the row number */ 

            for (c = 0; c < COLS; c++)
            {
                 printf("%d", X(r,c));
            }

            printf("\n");
        }

        free(p);
    }
    else
    {
        /* issue some silly error message */ 
    }

    return 0;
}

Humm. How about old fashion smoke and mirrors as an option?

#define ROWS  5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))

int main(void)
{
    int *p = (int *) malloc (ROWS * COLS * sizeof(int));
    if (p != NULL)
    {
        size_t r;
        size_t c;
        for (r = 0; r < ROWS; r++)
        {
            for (c = 0; c < COLS; c++)
            {
                 X(r,c) = r * c;  /* put some silly value in that position */ 
            }
        }

        /* Then show the contents of the array */ 
        for (r = 0; r < ROWS; r++)
        {
            printf("%d ", r);   /* Show the row number */ 

            for (c = 0; c < COLS; c++)
            {
                 printf("%d", X(r,c));
            }

            printf("\n");
        }

        free(p);
    }
    else
    {
        /* issue some silly error message */ 
    }

    return 0;
}
假装爱人 2024-07-18 21:13:08

使用 malloc(3) 分配第一个数组并放入由 malloc(3) 创建的指针应该与 array[r][c] 因为它应该等价于 *(*(array + r) + c),它是 C 标准中的。

Using malloc(3) for allocate the first array and putting in there pointers created by malloc(3) should work with array[r][c] because it should be equivalent to *(*(array + r) + c), it is in the C standard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文