Cprogramming 简明教程

Pointers and Multidimensional Arrays in C

在 C 语言中, array 是一个值集合,这些值类型相似,存储在连续的内存位置中。数组(一维或多维)中的每个元素由一个或多个唯一的整数索引标记。

In C language, an array is a collection of values of similar type stored in continuous memory locations. Each element in an array (one-dimensional or multi-dimensional) is identified by one or more unique integer indices.

另一方面, pointer 存储的是 variable 的地址。数组中第 0 个元素的地址是 pointer of the array 。您可以使用“解引用运算符”来访问指针引用的值。

A pointer, on the other hand, stores the address of a variable. The address of the 0th element in an array is the pointer of the array. You can use the "dereference operator" to access the value that a pointer refers to.

可以在 C 语言中声明一维、二维或多维数组。术语“维度”指的是标识集合中的元素所需的索引数量。

You can declare a one-dimensional, two-dimensional or multi-dimensional array in C. The term "dimension" refers to the number of indices required to identify an element in a collection.

Pointers and One-dimensional Arrays

在一维数组中,每个元素由一个整数标识。

In a one-dimensional array, each element is identified by a single integer:

int a[5] = {1, 2, 3, 4, 5};

此处,数字“1”位于第 0 个索引,“2”位于索引 1,依此类推。

Here, the number "1" is at the 0th index, "2" at index 1, and so on.

一个存储第 0 个元素地址的变量是其指针−

A variable that stores the address of 0th element is its pointer −

int *x = &a[0];

简单来说,数组的名称也指向第 0 个元素的地址。因此,您还可以使用此表达式−

Simply, the name of the array too points to the address of the 0th element. So, you can also use this expression −

int *x = a;

Example

由于指针的值将以数据类型的大小递增,“x++”将指针移动到数组中的下一个元素。

Since the value of the pointer increments by the size of the data type, "x++" moves the pointer to the next element in the array.

#include <stdio.h>

int main(){

   int arr[] = {1, 2, 3, 4, 5};
   int length = sizeof(arr) / sizeof(arr[0]);
   int i = 0;

   int *ptr = arr;

   while (i < length){
      printf("arr[%d]: %d \n", i, *(ptr + i));
      i++;
   }

   return 0;
}

当你运行这段代码时,它将产生以下输出:

When you run this code, it will produce the following output −

arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5

Pointers and Two-dimensional Arrays

如果一维数组像元素列表,那么二维数组就像表格或矩阵。

If a one-dimensional array is like a list of elements, a two-dimensional array is like a table or a matrix.

二维数组中的元素被认为在逻辑上排列成行和列。因此,任何元素的位置由两个索引确定,即其行号和列号。行索引和列索引都从“0”开始。

The elements in a 2D array can be considered to be logically arranged in rows and columns. Hence, the location of any element is decided by two indices, its row number and column number. Both row and column indexes start from "0".

int arr[2][2];

这样的数组表示为−

Such an array is represented as −

Col0

Col1

Col2

Row0

arr[0][0]

arr[0][1]

arr[0][2]

Row1

arr[1][0]

arr[1][1]

arr[1][2]

Row2

arr[2][0]

arr[2][1]

arr[2][2]

值得注意的是,表格排列仅仅是一种逻辑表示。编译器分配的是连续字节块。在 C 语言中,数组分配按行优先的方式进行,这意味着元素按行方式读入数组。

It may be noted that the tabular arrangement is only a logical representation. The compiler allocates a block of continuous bytes. In C, the array allocation is done in a row-major manner, which means the elements are read into the array in a row−wise manner.

此处,我们声明一个包含三行四列的二维数组(第一个方括号中的数字始终表示行数),如下所示:

Here, we declare a 2D array with three rows and four columns (the number in the first square bracket always refers to the number of rows) as −

int arr[3][4] = {
   {1, 2,  3,  4},
   {5, 6,  7,  8},
   {9, 10, 11, 12}
};

编译器将按行优先的顺序为上述二维数组分配内存。假设数组的第一个元素位于地址 1000,并且类型“int”的大小为 4 字节,那么数组元素将获得以下分配内存位置:

The compiler will allocate the memory for the above 2D array in a row−wise order. Assuming that the first element of the array is at the address 1000 and the size of type "int" is 4 bytes, the elements of the array will get the following allocated memory locations −

Row 0

Row 1

Row 2

Value

1

2

3

4

5

6

7

8

9

10

11

12

Address

1000

1004

1008

1012

1016

1020

1024

1028

1032

1036

我们将使用地址运算符 & 将数组 num 的第一个元素的地址分配给指针 ptr。

We will assign the address of the first element of the array num to the pointer ptr using the address of & operator.

int *ptr = &arr[0][0];

Example 1

如果指针递增 1,它将移动到下一个地址。“3×4”数组中的所有 12 个元素都可以通过循环访问,如下所示:

If the pointer is incremented by 1, it moves to the next address. All the 12 elements in the "3×4" array can be accessed in a loop as follows −

#include <stdio.h>

int main(){

   int arr[3][4] = {
      {1, 2,  3,  4},
      {5, 6,  7,  8},
      {9, 10, 11, 12},
   };

   // pointer ptr pointing at array num
   int *ptr = &arr[0][0];

   int i, j, k = 0;

   // print the elements of the array num via pointer ptr
   for (i = 0; i < 3; i++){
      for (j = 0; j < 4; j++){
         printf("%d   ", *(ptr + k));
         k++;
      }
      printf("\n");
   }

   return 0;
}

当你运行这段代码时,它将产生以下输出:

When you run this code, it will produce the following output −

1   2   3   4
5   6   7   8
9   10   11   12

通常情况下,数组的任何元素的地址都通过以下公式获得:

In general, the address of any element of the array by with the use the following formula −

add of element at ith row and jth col = baseAddress + [(i * no_of_cols + j) * sizeof(array_type)]

在我们的 3×4 数组中:

In our 3×4 array,

add of arr[2][4] = 1000 + (2*4 + 2)*4 = 1044

你可以参考上述数字,它确认 “arr[3][4]” 的地址是 1044。

You can refer to the above figure and it confirms that the address of "arr[3][4]" is 1044.

Example 2

使用 dereference pointer 获取地址中的值。让我们使用这个公式,通过指针遍历数组:

Use the dereference pointer to fetch the value at the address. Let us use this formula to traverse the array with the help of its pointer −

#include <stdio.h>

int main(){

   // 2d array
   int arr[3][4] = {
      {1, 2,  3,  4},
      {5, 6,  7,  8},
      {9, 10, 11, 12}
   };

   int ROWS = 3, COLS = 4;
   int i, j;

   // pointer
   int *ptr = &arr[0][0];

   // print the element of the array via pointer ptr
   for (i = 0; i < ROWS; i++){
      for (j = 0; j < COLS; j++) {
         printf("%4d ",*(ptr + (i * COLS + j)));
      }
      printf("\n");
   }

   return 0;
}

当你运行这段代码时,它将产生以下输出:

When you run this code, it will produce the following output −

   1    2    3    4
   5    6    7    8
   9   10   11   12

Pointers and Three-dimensional Arrays

三维数组是二维数组的数组。这种数组使用三个下标声明:

A three-dimensional array is an array of two-dimensional arrays. Such an array is declared with three subscripts −

int arr [x] [y] [j];

该数组可视为 “x” 层表格,每个表格具有 “x” 行和 “y” 列。

This array can be considered as "x" number of layers of tables, each table having "x" rows and "y" number of columns.

3D 数组的示例为:

An example of a 3D array is −

int arr[3][3][3] ={
   { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
   { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
   { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
};

指向 3D 数组的指针可以声明为:

A pointer to the 3D array can be declared as −

int * ptr = &arr[0][0][0];

了解到数组本身的名称是第 0 个元素的地址,我们可以将 3D 数组的指针写入为:

Knowing that, the name of the array itself is the address of 0th element, we can write the pointer of a 3D array as −

int * ptr = arr;

“x” 行和 “y” 列的每一层占据:

Each layer of "x" rows and "y" columns occupies −

x * y * sizeof(data_type)

字节数。假设上文声明的 3D 数组 “arr” 分配的内存从地址 1000 开始,第二层(“i = 1”)从 1000 +(3 × 3)× 4 = 1036 字节位置开始。

Number of bytes. Assuming that the memory allocated to the 3D array "arr" as declared above starts from the address 1000, the second layer (with "i = 1") starts at 1000 + (3 × 3) × 4 = 1036 byte position.

ptr = Base address of 3D array arr

如果 JMAX 是行数,KMAX 是列数,则第 1 个切片中第 0 行第 0 列的元素的地址为:

If JMAX is the number of rows and KMAX is the number of columns, then the address of the element at the 0th row and the 0th column of the 1st slice is −

arr[1][0][0] = ptr + (1 * JMAX * KMAX)

为了获得第 i 个切片的第 j 行第 k 列的元素的值,公式可表示为:

The formula to obtain the value of an element at the jth row and kth column of the ith slice can be given as −

arr[i][j][k] = *(ptr + (i * JMAX*KMAX) + (j*KMAX + k))

Example: Printing a 3D Array using Pointer Dereferencing

让我们使用此公式,通过指针取消引用来打印 3D 数组:

Let us use this formula to print the 3D array with the help of the pointer dereferencing −

#include <stdio.h>

int main(){

   int i, j, k;
   int arr[3][3][3] = {
      { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
      { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
      { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
   };

   int JMAX = 3, KMAX = 3;
   int *ptr = arr; 	// &arr[0][0][0];

   for(i = 0; i < 3; i++){
      for(j = 0; j < 3; j++){
         for(k = 0; k < 3; k++){
            printf("%d ",*(ptr+(i*JMAX*KMAX)+(j*KMAX+k)));
         }
         printf("\n");
      }
      printf("\n");
   }

   return 0;
}

当你运行这段代码时,它将产生以下输出:

When you run this code, it will produce the following output −

11 12 13
14 15 16
17 18 19

21 22 23
24 25 26
27 28 29

31 32 33
34 35 36
37 38 39

通常,使用指针访问数组与使用下标表示访问数组非常相似。两者的主要区别在于,带有下标的数组声明会静态分配内存,而我们可以使用指针进行动态内存分配。

In general, accessing an array with a pointer is quite similar to accessing an array with subscript representation. The main difference between the two is that the subscripted declaration of an array allocates the memory statically, whereas we can use pointers for dynamic memory allocation.

要将 multi-dimensional array 传递给函数,需要使用指针而不是下标。但是,使用下标数组比使用指针更方便,这对于初学者来说可能很困难。

To pass a multi-dimensional array to a function, you need to use pointers instead of subscripts. However, using a subscripted array is more convenient than using pointers, which can be difficult for new learners.