我并不真正理解C中的一些基本内容,比如动态分配数组数组。 我知道你可以这样做:
int **m;
为了声明一个二维数组(随后将使用某些* alloc函数进行分配)。也可以通过*(*(m + line) + column)
“轻松”访问它。但是我应该如何为该数组中的元素赋值?使用gcc时,以下语句m[line][column] = 12;
会因分段错误而失败。
任何文章/文档将不胜感激。 : - )
答案 0 :(得分:34)
m[line][column] = 12
语法正常(提供line
且column
在范围内)。
但是,您没有编写用于分配代码的代码,因此很难判断它是错还是正确。它应该是
的内容m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
一些旁注:
答案 1 :(得分:5)
您的语法m [line] [colummn]是正确的。但是为了在C中使用2D数组,必须为它分配内存。例如,此代码将为给定行和列的表分配内存。
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的错误检查。一个真正的解决方案应该包括它们。
答案 2 :(得分:3)
它不是一个二维数组 - 它是一个数组数组 - 因此它需要多个分配。
答案 3 :(得分:2)
这是quinmars' solution的修改版本,它只分配一个内存块,并且可以通过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;
答案 4 :(得分:1)
虽然我同意其他答案,但在大多数情况下,一次分配整个数组会更好,因为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;
}
要释放数组,只需执行以下操作:
free(*array); free(array);
注意:此解决方案仅在您不想更改行的顺序时才有效,因为您可能会丢失第一个元素的地址,稍后需要释放该数组。
答案 5 :(得分:1)
姆。如何选择旧时尚的烟雾和镜子?
#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;
}
答案 6 :(得分:0)
使用malloc(3)
分配第一个数组并输入由malloc(3)
创建的指针应该与array[r][c]
一起使用,因为它应该等同于*(*(array + r) + c)
,它位于C标准。