Is it possible to create statically in C a 2d array of pointers to 2d arrays, like:
是否可能在C中静态地创建一个指向2d数组的2d数组,比如:
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
char (*parr[m][n])[p][q] = {{&arr1, 0, &arr2, 0}};
int main() {
return 0;
}
The 2d array of pointers parr
is sparse, with some values to 0 (NULL), which is why I don't want to use a 4d array in the first place.
指针parr的2d数组是稀疏的,有些值为0 (NULL),这就是为什么我不想首先使用4d数组的原因。
This compiles, but I get the following warning:
这个编译,但我得到以下警告:
warning: initialization from incompatible pointer type
警告:初始化来自不兼容的指针类型
With the following command:
使用下面的命令:
gcc -Wall -Wextra -pedantic -std=c99 test.c
-Wextra -pedantic -std=c99 test.c
What is wrong?
是什么错了吗?
4 个解决方案
#1
2
The problem is that when you declare pointers, arrays and array pointers, the [] takes precedence over * unless you add parenthesis. This is why you declare an array pointer as (*parr)[]
rather than *parr[]
, since the latter gives an array of pointers instead.
问题是,当您声明指针、数组和数组指针时,[]优先于*,除非您添加括号。这就是为什么您声明一个数组指针(*parr)[]而不是*parr[],因为后者给出了一个指针数组。
Similarly, when declaring a pointer to a 2D array, you would type (*parr)[m][n]
. So it seems logical that an array of 2D-array pointers should be declared as ((*parr)[m][n])[p][q])
. But the outer parenthesis here actually does nothing, that expression is equivalent to (*parr)[m][n][p][q]
. And that's an array pointer to a 4D array! Which is why you get compiler warnings.
类似地,在声明指向2D数组的指针时,您将输入(*parr)[m][n]。因此,一个由2d数组指针组成的数组应该被声明为(*parr)[m][n])[p][q]。但是这个外括号实际上什么都没有,这个表达式等价于(*parr)[m][n][p][q]。这是一个数组指向4D数组的指针!这就是为什么你会得到编译器警告。
Now what you actually want is to get an array of array pointers to 2D arrays, is something like char (*parr[p][q])[m][n]
. Which looks rather insane, nobody will understand a declaration like that.
现在你真正想要的是得到一个数组指针到二维数组,类似于char (*parr[p][q])[m][n]。这看起来相当疯狂,没有人会理解这样的宣言。
The only sane way to write code like this is through typedefs:
编写这样的代码的唯一合理方法是通过typedef:
typedef char arr_t[m][n];
arr_t arr1 = {{0}};
arr_t arr2 = {{0}};
arr_t* parr[p][q] =
{
{&arr1, 0},
{&arr2, 0}
};
#2
1
I think what you meant to do is the following:
我认为你想做的是:
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
typedef char (*some_type)[n]; // type of arr1 and arr2
some_type parr[p][q] = {{arr1, NULL}, {arr2, NULL}}; //array containing arr1 and arr2
You can then access parr
e.g by
然后您可以访问parr e。克的
printf("%c\n", parr[0][0][0][0]);
which will print arr1[0][0]
.
这将打印arr1[0][0]。
#3
1
In the declaration of parr I think you meant to use p and q as its dimensions:
在parr的声明中,我认为您是想用p和q作为它的维度:
$ cat test.c
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
char (*parr[p][q])[m][n] = {{&arr1, NULL}, {&arr2, NULL}};
int main(void)
{
printf("%d\n", (*parr[0][0])[0][0]);
return 0;
}
This compiles cleanly with GCC 4.8.2:
这是用GCC 4.8.2编写的:
$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -ansi -fsanitize=address -g -pedantic -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -o test test.c
$
#4
0
Here would be my solution -- i prefer using static 1D arrays rather than static 2D arrays due pointer arithmetic (i like to keep things simple):
这里是我的解决方案——我更喜欢使用静态的1D数组而不是静态的二维数组,因为指针算法(我喜欢保持简单):
PS. i would suggestin using m!=n and p!=q for testing, so you can catch possible indexing errors!
我建议用m!= n和p !=q进行测试,以便您可以捕获可能的索引错误!
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m*n] = {0};
char arr2[m*n] = {0};
typedef char array_2d[m][n];
char* parr[p][q] = { {(char*)arr1, NULL}, { (char*)arr2, NULL} };
int main()
{
for (int i = 0; i < m; i ++ )
for (int j = 0; j < n; j ++ )
{
arr1[i*n + j] = i + j;
arr2[i*n + j] = i - j;
}
for (int i = 0; i < m; i ++ )
{
for (int j = 0; j < n; j ++ )
{
char* arr1_ptr = parr[0][0];
char* arr2_ptr = parr[1][0];
printf("%d", (int)(arr1_ptr[i*n + j] - arr2_ptr[i*n + j] ));
}
printf("\n");
}
return 0;
}
#1
2
The problem is that when you declare pointers, arrays and array pointers, the [] takes precedence over * unless you add parenthesis. This is why you declare an array pointer as (*parr)[]
rather than *parr[]
, since the latter gives an array of pointers instead.
问题是,当您声明指针、数组和数组指针时,[]优先于*,除非您添加括号。这就是为什么您声明一个数组指针(*parr)[]而不是*parr[],因为后者给出了一个指针数组。
Similarly, when declaring a pointer to a 2D array, you would type (*parr)[m][n]
. So it seems logical that an array of 2D-array pointers should be declared as ((*parr)[m][n])[p][q])
. But the outer parenthesis here actually does nothing, that expression is equivalent to (*parr)[m][n][p][q]
. And that's an array pointer to a 4D array! Which is why you get compiler warnings.
类似地,在声明指向2D数组的指针时,您将输入(*parr)[m][n]。因此,一个由2d数组指针组成的数组应该被声明为(*parr)[m][n])[p][q]。但是这个外括号实际上什么都没有,这个表达式等价于(*parr)[m][n][p][q]。这是一个数组指向4D数组的指针!这就是为什么你会得到编译器警告。
Now what you actually want is to get an array of array pointers to 2D arrays, is something like char (*parr[p][q])[m][n]
. Which looks rather insane, nobody will understand a declaration like that.
现在你真正想要的是得到一个数组指针到二维数组,类似于char (*parr[p][q])[m][n]。这看起来相当疯狂,没有人会理解这样的宣言。
The only sane way to write code like this is through typedefs:
编写这样的代码的唯一合理方法是通过typedef:
typedef char arr_t[m][n];
arr_t arr1 = {{0}};
arr_t arr2 = {{0}};
arr_t* parr[p][q] =
{
{&arr1, 0},
{&arr2, 0}
};
#2
1
I think what you meant to do is the following:
我认为你想做的是:
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
typedef char (*some_type)[n]; // type of arr1 and arr2
some_type parr[p][q] = {{arr1, NULL}, {arr2, NULL}}; //array containing arr1 and arr2
You can then access parr
e.g by
然后您可以访问parr e。克的
printf("%c\n", parr[0][0][0][0]);
which will print arr1[0][0]
.
这将打印arr1[0][0]。
#3
1
In the declaration of parr I think you meant to use p and q as its dimensions:
在parr的声明中,我认为您是想用p和q作为它的维度:
$ cat test.c
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
char (*parr[p][q])[m][n] = {{&arr1, NULL}, {&arr2, NULL}};
int main(void)
{
printf("%d\n", (*parr[0][0])[0][0]);
return 0;
}
This compiles cleanly with GCC 4.8.2:
这是用GCC 4.8.2编写的:
$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -ansi -fsanitize=address -g -pedantic -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -o test test.c
$
#4
0
Here would be my solution -- i prefer using static 1D arrays rather than static 2D arrays due pointer arithmetic (i like to keep things simple):
这里是我的解决方案——我更喜欢使用静态的1D数组而不是静态的二维数组,因为指针算法(我喜欢保持简单):
PS. i would suggestin using m!=n and p!=q for testing, so you can catch possible indexing errors!
我建议用m!= n和p !=q进行测试,以便您可以捕获可能的索引错误!
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m*n] = {0};
char arr2[m*n] = {0};
typedef char array_2d[m][n];
char* parr[p][q] = { {(char*)arr1, NULL}, { (char*)arr2, NULL} };
int main()
{
for (int i = 0; i < m; i ++ )
for (int j = 0; j < n; j ++ )
{
arr1[i*n + j] = i + j;
arr2[i*n + j] = i - j;
}
for (int i = 0; i < m; i ++ )
{
for (int j = 0; j < n; j ++ )
{
char* arr1_ptr = parr[0][0];
char* arr2_ptr = parr[1][0];
printf("%d", (int)(arr1_ptr[i*n + j] - arr2_ptr[i*n + j] ));
}
printf("\n");
}
return 0;
}