Can';我不能完全理解2d数组中的指针

Can';我不能完全理解2d数组中的指针,c,pointers,multidimensional-array,C,Pointers,Multidimensional Array,我通过上网做了一些事情,但这里缺少的是我的代码 void draw_way(int *arr,int lenght_row,int lenght_column) { int s1 = 0, s2 = 0; for (s1 = 0; s1 < lenght_row; s1++) { for (s2 = 0; s2 < lenght_column; s2++) { if (*((arr + s1 * lenght_row) + s2) == 1)

我通过上网做了一些事情,但这里缺少的是我的代码

void draw_way(int *arr,int lenght_row,int lenght_column) {
int s1 = 0, s2 = 0;
for (s1 = 0; s1 < lenght_row; s1++)
{
    for (s2 = 0; s2 < lenght_column; s2++) {
        if (*((arr + s1 * lenght_row) + s2) == 1)
        {
            printf("S");
        }
        else if (*((arr + s1 * lenght_row) + s2) == 2)
        {
            printf("G");
        }
        else if(*((arr + s1 * lenght_row) + s2) == 3)
        {
            printf("#");
        }
        else if (*((arr + s1 * lenght_row) + s2) == 4)
        {
            printf(".");
        }
    }
    printf("\n");
}
void draw\u way(int*arr、int lenght\u行、int lenght\u列){
int s1=0,s2=0;
对于(s1=0;s1

它实际上是在打印一个迷宫,但并不重要。我想了解的是,为什么ı必须使用
*((arr+s1*lenght_row)+s2)
如果ı使用
*(*(arr+s1)+s2)为什么这不起作用
lenght\u row'的作用。

arr是一个平面数组,而不是多维数组。它通过传入网格大小来模拟多维数组。因此,如果它是5x2,那么作为平面数组的arr将是10个整数长,而不是由5行和另一个2列数组组成的数组

因此,它使用简单的指针算法通过平面数组索引计算来模拟r、c维度


((arr+s1*lenght_row)+s2)
arr是一个平面数组,而不是多维数组。它通过传入网格大小来模拟多维数组。因此,如果它是5x2,那么作为平面数组的arr将是10个整数长,而不是由5行和另一个2列数组组成的数组

因此,它使用简单的指针算法通过平面数组索引计算来模拟r、c维度


((arr+s1*长度行)+s2)
对于任何数组或指针
arr
和索引
i
,表达式
*(arr+i)
完全等于
arr[i]

如果我们对
*(*(arr+s1)+s2)
做这个翻译,那就是
(arr[s1])[s2]
(或者
arr[s1][s2]
)。既然
arr
不是指向指针(或者数组数组)的指针,那么
arr[s1][s2]
就没有意义了

相反,您可以使用数组(其第一个元素由
arr
指向)模拟2d数组(数组的数组),并使用算术计算该数组中的单个索引

这在动态分配内存中非常常见,在动态分配内存中,您使用单个连续区域或内存,而不是使用(指向指针的指针)


用一个例子可能更容易理解

假设我们想要一个由2×3个元素组成的二维数组。我们可以使用动态分配作为交错数组来创建它:

int **arr;
arr = malloc(2 * sizeof *arr);  // First dimension
for (size_t i = 0; i < 2; ++i)
    arr[i] = malloc(3 * sizeof *arr[i]);  // Second dimension
但这很难动态处理,因此我们分配一个
2*3
元素的连续内存区域:

int *arr;
arr = malloc(2 * 3 * sizeof *arr);

不幸的是,这不能像锯齿状数组或数组数组那样直观地建立索引(即,
arr[0][1]
不可能)。但通过一些巧妙的算法,这是可能的:
arr[row\u index*row\u length+column\u index]
类似于
arr[row\u index][column\u index]
(对于锯齿状数组或数组).

对于任何数组或指针
arr
和索引
i
,表达式
*(arr+i)
完全等于
arr[i]

如果我们对
*(*(arr+s1)+s2)
做这个翻译,那就是
(arr[s1])[s2]
(或者
arr[s1][s2]
)。既然
arr
不是指向指针(或者数组数组)的指针,那么
arr[s1][s2]
就没有意义了

相反,您可以使用数组(其第一个元素由
arr
指向)模拟2d数组(数组的数组),并使用算术计算该数组中的单个索引

这在动态分配内存中非常常见,在动态分配内存中,您使用单个连续区域或内存,而不是使用(指向指针的指针)


用一个例子可能更容易理解

假设我们想要一个由2×3个元素组成的二维数组。我们可以使用动态分配作为交错数组来创建它:

int **arr;
arr = malloc(2 * sizeof *arr);  // First dimension
for (size_t i = 0; i < 2; ++i)
    arr[i] = malloc(3 * sizeof *arr[i]);  // Second dimension
但这很难动态处理,因此我们分配一个
2*3
元素的连续内存区域:

int *arr;
arr = malloc(2 * 3 * sizeof *arr);

不幸的是,这不能像锯齿状数组或数组数组那样直观地建立索引(即,
arr[0][1]
不可能)。但通过一些巧妙的算法,这是可能的:
arr[row\u index*row\u length+column\u index]
类似于
arr[row\u index][column\u index]
(对于锯齿状数组或数组).

首先,if-else语句中的表达式如下所示

if (*((arr + s1 * lenght_row) + s2) == 1)
是不正确的。应该有

if (*((arr + s1 * lenght_column) + s2) == 1)
参数arr声明为like

int *arr
具有类型
int*
。因此,像
*arr
那样取消对指针的引用,您将得到一个int类型的对象,您可能不会对其应用取消引用运算符

所以这个表达式

*(*(arr+s1)+s2)
不正确。子表达式
*(arr+s1)
的类型为int。因此第二次使用运算符*会产生编译错误

在所示函数中,使用指向一维数组的指针模拟了二维数组。也就是说,一维数组在逻辑上按长度\列元素分割为块

这是一个演示程序

#include <stdio.h>

#define ROW_LENGTH      2
#define COLUMN_LENGTH   3

void display( const int *arr, size_t row_length, size_t column_length )
{
    for ( size_t i = 0; i < row_length; i++ )
    {
        for ( size_t j = 0; j < column_length; j++ )
        {
            printf( "%d ", *( arr + i * column_length + j ) );
        }
        putchar( '\n' );
    }
}

int main(void) 
{
    int arr[ROW_LENGTH * COLUMN_LENGTH] = { 1, 2, 3, 4, 5, 6 };

    display( arr, ROW_LENGTH, COLUMN_LENGTH );

    return 0;
}

首先,if-else语句中的表达式如下

if (*((arr + s1 * lenght_row) + s2) == 1)
是不正确的。应该有

if (*((arr + s1 * lenght_column) + s2) == 1)
参数arr声明为like

int *arr
具有类型
int*
。因此,像
*arr
那样取消对指针的引用,您将得到一个int类型的对象,您可能不会对其应用取消引用运算符

所以这个表达式

*(*(arr+s1)+s2)
不正确。子表达式
*(arr+s1)
的类型为int。因此第二次使用运算符*会产生编译错误