int **
不再是一个二维数组; 它是一个指向指针的指针,或者更具体地说,在我们的情况下是指向指针数组的指针。
这就是为什么您在将指针分配给2D数组 ((int[3][2]){{0,0}, {0,0}, {0,0}}
) 时会遇到问题的原因。
要初始化int**
,您需要类似于以下内容:
xy_t xy = {
.M = 3,
.N = 2,
.x = (int[3]){ 0,0,0 },
.y = (int*[3]){
(int[2]){ 0,0 },
(int[2]){ 0,0 },
(int[2]){ 0,0 },
},
};
你也可以让编译器来计数:
xy_t xy = {
.M = 3,
.N = 2,
.x = (int[]){ 0,0,0 },
.y = (int*[]){
(int[]){ 0,0 },
(int[]){ 0,0 },
(int[]){ 0,0 },
},
};
尽管不是二维数组,仍然可以使用xy.y[ i ][ j ]
来访问y[i][j]。
上述结构需要M+2个指针和M+3个内存块。如果您想要使结构更小,可以使用以下结构,它只使用了2个指针和3个内存块:
typedef struct {
const int M;
const int N;
int *x;
int *y;
} xy_t;
xy_t xy = {
.M = 3,
.N = 2,
.x = (int[]){ 0,0,0 },
.y = (int[]){ 0,0, 0,0, 0,0 },
};
要访问y [i] [j],您可以使用xy.y [i * xy.N + j]
。
您还可以将其强制转换为指向2D数组的指针,以便使用y [i] [j]
。操作如下:
int (*y)[ xy.M ][ xy.N ] = (int(*)[ xy.M ][ xy.N ])xy.y;
你甚至可以让它更小!以下代码使用零指针和仅一个内存块。
typedef struct {
const int M;
const int N;
int xy[];
} xy_t;
xy_t xy = {
.M = 3,
.N = 2,
.xy = {
0,0,0,
0,0, 0,0, 0,0
},
};
你可以使用xy.xy[ i ]
来访问x[i]。
你可以使用xy.xy[ xy.M + i * xy.N + j ]
来访问y[i][j]。
或者:
int (*x)[ xy.M ] = (int(*)[ xy.M ])xy.xy;
int (*y)[ xy.M ][ xy.N ] = (int(*)[ xy.M ][ xy.N ])( xy.xy + xy.M );
x[i]
y[i][j]
话虽如此,gcc发出警告
警告:初始化灵活数组成员[-Wpedantic]
因此,这个最后的解决方案很可能是非标准的。
xy_t
实例呢?比如xy_t xy_t_create(unsigned int m, unsigned int n);
你还需要一个清理函数来释放数组。 - no more sigsegvx
和y
都是指针,所以{.x=(int *)0, .y=(int**)0}
可以正常工作,然后它们可以分配给要处理的数组。或者,创建一个一维数组,例如 x1[M]={0},和一个二维数组,例如 y2[M][N]={{0}},然后分别使用这两个数组初始化 x 和 y。 - user6099871