我想在 C 中动态分配(malloc)一个多维字符数组。该数组将具有以下格式:
char *array[3][2] = {
{"one","two"},
{"three","four"},
{"five","six"}
};
在创建数组之前,我已经知道多维数组中所有字符数组的行数和长度。我将如何 malloc 这样的字符数组?
提前致谢!
我想在 C 中动态分配(malloc)一个多维字符数组。该数组将具有以下格式:
char *array[3][2] = {
{"one","two"},
{"three","four"},
{"five","six"}
};
在创建数组之前,我已经知道多维数组中所有字符数组的行数和长度。我将如何 malloc 这样的字符数组?
提前致谢!
这是分配 char * 的二维数组的一种方法。
之后,您可以分配内容,例如 a[1][2] = "foo"; 请注意,数组的元素被初始化为 (char *)0。
#include <stdio.h>
#include <stdlib.h>
char ***alloc_array(int x, int y) {
char ***a = calloc(x, sizeof(char **));
for(int i = 0; i != x; i++) {
a[i] = calloc(y, sizeof(char *));
}
return a;
}
int main() {
char ***a = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
[Charlies-MacBook-Pro:~] crb% cc xx.c
[Charlies-MacBook-Pro:~] crb% a.out
foo
首先,数组通常以 Row Major 形式存储,因此实际上您有一个向量长度为六个元素,每个条目是一个char *
ptr。即按行、列标记的元素类似于:
char *r1c1, *r1c2, *r2c1, *r2c2, *r3c1, *r3c1;
因此,做一个简单的 malloc:
char *matrix = malloc(3*2*sizeof(char *));
然后将元素设置为:
matrix[0] = "one";
matrix[1] = "two";
matrix[2] = "three";
matrix[3] = "four";
matrix[4] = "five";
matrix[5] = "six";
最后,为了测试这个,编写一个嵌套循环:
for (int r=0; r<3; r++)
{
for (int c=0; c<2; c++);
{
printf("%s\n",matrix[r][c]);
}
}
请注意,如何首先将矩阵视为向量,然后将其视为矩阵。C无所谓!!
保持简单,谢尔顿。您选择的答案使用 a char ***
,它甚至不接近 a 的等价物char *[2][3]
。不同之处在于分配的数量......一个数组只需要一个。
例如,这就是我将如何改造您选择的答案。注意它有多简单?
#include <stdio.h>
#include <stdlib.h>
void *alloc_array(size_t x, size_t y) {
char *(*a)[y] = calloc(x, sizeof *a);
return a;
}
int main() {
char *(*a)[2] = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
char *array[3][2] 只不过是一个二维指针数组。因此,您需要 3*2*sizeof(char *) 的存储空间来存储指针。
正如您所提到的,指针实际上指向以零结尾的字符串,您可能希望字符串也被 malloc'ed。假设所有字符串的总长度为N(包括零终止),则需要的存储空间为(3*2*sizeof(char *) + N)。
为上述大小分配内存并自己复制字符串,如下所示。
在下面的代码中,我们假设列数 (2) 是一个常数
char *(*dst)[2] = (char *(*)[2]) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i][j] = s;
s += strlen(s)+1;
}
}
注意:在上面的代码中,'dst' 是一个指针,指向 char * 的二维数组的第一行。
如果列数不是恒定的,则语法会发生一些变化,但存储大小是相同的。
char **dst = (char **) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i*2 + j] = s; /* 2 is the number of columns */
s += strlen(s)+1;
}
}
注意:这里的 'dst' 是指向 char * 的一维数组的第一个元素的指针,并且二维索引是手动完成的。
上面的例子假设字符串长度在分配后不会改变。如果分配后字符串可以随时更改,那么最好为每个字符串单独分配。
如果您到达此页面,想要创建一个类似的数组int myarray[n][M]
(这与问题略有不同,因为他们想要一个字符串数组),其中M
是固定的并且n
可以变化(例如,如果您想要一个坐标数组...... ),那么你可以这样做:
int (*p)[M] = malloc(n*sizeof *p);
然后p[i][j]
像以前一样使用。然后,您将获得sizeof p[i] = M*sizeof(int)
:
#include <stdio.h>
#include <stdlib.h>
#define M 6
int main(int argc, char *argv[])
{
int n = 4;
int (*p)[M] = malloc(n*sizeof *p);
printf("Size of int: %lu\n", sizeof(int));
printf("n = %d, M = %d\n", n, M);
printf("Size of p: %lu (=8 because pointer in 64bits = 8 bytes)\n", sizeof p);
printf("Size of *p: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof *p);
printf("Size of p[0]: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof p[0]);
// Assign
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
(p[i])[j] = i*10+j;
}
}
// Display
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
printf("%2d; ", (p[i])[j]);
}
printf("\n");
}
return 0;
}
这使:
Size of int: 4
n = 4, M = 6
Size of p: 8 (=8 because pointer in 64bits = 8 bytes)
Size of *p: 24 (=M*sizeof(int) because each case is an array of length M)
Size of p[0]: 24 (=M*sizeof(int) because each case is an array of length M)
0; 1; 2; 3; 4; 5;
10; 11; 12; 13; 14; 15;
20; 21; 22; 23; 24; 25;
30; 31; 32; 33; 34; 35;