指向二维数组的指针的静态二维数组

时间:2022-09-30 21:30:54

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;
}