1. 主页
  2. 文档
  3. C语言教程
  4. C语言指针
  5. 指向数组的指针

指向数组的指针

指向数组的指针

考虑以下程序: 

#include <iostream>
using namespace std;

int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
int *ptr = arr;

cout <<"\n"<< ptr;
return 0;
}
#include<stdio.h>

int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
int *ptr = arr;

printf("%p\n", ptr);
return 0;
}

在这个程序中,我们有一个指针ptr指向数组的第 0元素。类似地,我们也可以声明一个指针,它可以指向整个数组,而不是只指向数组的一个元素。这个指针在讨论多维数组时很有用。 
语法:

data_type (*var_name)[size_of_array] ;

例子: 

int (*ptr)[10];

这里ptr是可以指向 10 个整数数组的指针。由于下标的优先级高于间接,因此有必要将间接运算符和指针名称括在括号内。这里 ptr 的类型是“指向 10 个整数数组的指针”。 
注意:指向数组第 0元素的指针和指向整个数组的指针是完全不同的。以下程序显示了这一点: 

// C++ program to understand difference between
// pointer to an integer and pointer to an
// array of integers.
#include <iostream>
using namespace std;
int main()
{
// Pointer to an integer
int *p;

// Pointer to an array of 5 integers
int (*ptr)[5];
int arr[5];

// Points to 0th element of the arr.
p = arr;

// Points to the whole array arr.
ptr = &arr;

cout << "p =" << p <<", ptr = "<< ptr<< endl;
p++;
ptr++;
cout << "p =" << p <<", ptr = "<< ptr<< endl;

return 0;
}
// C program to understand difference between
// pointer to an integer and pointer to an
// array of integers.
#include<stdio.h>

int main()
{
// Pointer to an integer
int *p;

// Pointer to an array of 5 integers
int (*ptr)[5];
int arr[5];

// Points to 0th element of the arr.
p = arr;

// Points to the whole array arr.
ptr = &arr;

printf("p = %p, ptr = %p\n", p, ptr);

p++;
ptr++;

printf("p = %p, ptr = %p\n", p, ptr);

return 0;
}

输出: 

p = 0x7fff4f32fd50,ptr = 0x7fff4f32fd50
p = 0x7fff4f32fd54,ptr = 0x7fff4f32fd64

p : 是指向数组 arr 的第 0元素的,而ptr是指向整个数组arr的指针。 

  • p的基本类型是 int 而ptr的基本类型是“5 个整数的数组”。
  • 我们知道指针运算是相对于基本大小执行的,所以如果我们写 ptr++,那么指针ptr将向前移动 20 个字节。

下图显示了指针 p 和 ptr。较暗的箭头表示指向数组的指针。 

在取消引用指针表达式时,我们会得到该指针表达式指向的值。指向数组的指针指向一个数组,所以在解引用它时,我们应该得到数组,数组的名称表示基地址。因此,每当取消引用指向数组的指针时,我们都会得到它指向的数组的基地址。 

// C++ program to illustrate sizes of
// pointer of array
#include <bits/stdc++.h>
using namespace std;

int main()
{
int arr[] = { 3, 5, 6, 7, 9 };
int *p = arr;
int (*ptr)[5] = &arr;

cout << "p = "<< p <<", ptr = " << ptr << endl;
cout << "*p = "<< *p <<", *ptr = " << *ptr << endl;

cout << "sizeof(p) = "<< sizeof(p) <<
", sizeof(*p) = " << sizeof(*p) << endl;
cout << "sizeof(ptr) = "<< sizeof(ptr) <<
", sizeof(*ptr) = " << sizeof(*ptr) << endl;
return 0;
}
// C program to illustrate sizes of
// pointer of array
#include<stdio.h>

int main()
{
int arr[] = { 3, 5, 6, 7, 9 };
int *p = arr;
int (*ptr)[5] = &arr;

printf("p = %p, ptr = %p\n", p, ptr);
printf("*p = %d, *ptr = %p\n", *p, *ptr);

printf("sizeof(p) = %lu, sizeof(*p) = %lu\n",
sizeof(p), sizeof(*p));
printf("sizeof(ptr) = %lu, sizeof(*ptr) = %lu\n",
sizeof(ptr), sizeof(*ptr));
return 0;
}

输出:

p = 0x7ffde1ee5010,ptr = 0x7ffde1ee5010
*p = 3,*ptr = 0x7ffde1ee5010
sizeof(p) = 8, sizeof(*p) = 4
sizeof(ptr) = 8, sizeof(*ptr) = 20

指向多维数组的指针:

指针和二维数组:在二维数组中,我们可以使用两个下标来访问每个元素,其中第一个下标代表行号,第二个下标代表列号。二维数组的元素也可以在指针符号的帮助下访问。假设 arr 是一个二维数组,我们可以使用指针表达式*(*(arr + i) + j)访问数组的任何元素arr[i][j]。现在我们将看到如何导出这个表达式。 让我们采用一个二维数组arr[3][4]: 

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

由于计算机中的内存是线性组织的,因此不可能将二维数组存储在行和列中。行和列的概念只是理论上的,实际上,二维数组以行优先顺序存储,即行彼此相邻放置。下图显示了上述二维数组将如何存储在内存中。

每一行都可以被认为是一个一维数组,因此二维数组可以被认为是一个接一个放置的一维数组的集合。换句话说,我们可以说是一个接一个放置的二维数组。所以这里的arr是一个由 3 个元素组成的数组,其中每个元素是一个由 4 个整数组成的一维数组。 
我们知道数组的名称是一个常量指针,它指向第 0一维数组并包含地址 5000。由于arr是“指向 4 个整数数组的指针”,根据指针算法,表达式 arr + 1 将表示地址 5016,表达式 arr + 2 将表示地址 5032。 
所以我们可以说arr指向第 0一维数组,arr + 1指向第一个一维数组,arr + 2指向第二个一维数组。 

一般来说,我们可以写: 

arr + i Points to ith element of arr ->
Points to ith 1-D array
  • 由于ARR + i指向我的元件ARR,上解引用它会得到我的元件ARR这当然是一个1-d阵列。因此,表达式*(arr + i)为我们提供了第 i一维数组的基地址。
  • 我们知道,指针表达式*(arr + i)等价于下标表达式arr[i]。所以*(arr + i)与arr[i]相同,为我们提供了第 i一维数组的基地址。
  • 要访问二维数组的单个元素,我们应该能够访问第 i个一维数组的任何第 j元素。
  • 由于*(arr + i)的基类型是int并且它包含第 i个一维数组的第 0元素的地址,我们可以通过添加整数值来获得第 i一维数组中后续元素的地址到*(arr + i)
  • 例如*(ARR + I)+ 1将代表1个的地址ST 1个的元件第一我的元件1-d阵列和*(ARR + I)2将表示2的地址的i个元素1 -D 数组。
  • 类似地 *(arr + i) + j 将表示i一维数组的j元素的地址。在取消引用这个表达式时,我们可以获得i一维数组的j元素。
  • 指针和三维数组
    在三维数组中,我们可以使用三个下标访问每个元素。让我们采用一个 3-D 数组- 
int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32 }} };

我们可以认为一个三维数组是一个二维数组的数组,即一个三维数组的每个元素都被认为是一个二维数组。3-D 数组arr可以被认为是由两个元素组成的数组,其中每个元素都是一个 2-D 数组。数组arr的名称是指向第 0二维数组的指针。 

因此,指针表达式*(*(*(arr + i ) + j) + k) 等价于下标表达式 arr[i][j][k]。 
我们知道表达式 *(arr + i) 等价于 arr[i] 并且表达式 *(*(arr + i) + j) 等价于 arr[i][j]。所以我们可以说 arr[i] 代表第 i二维数组的基地址,而 arr[i][j] 代表第 j一维数组的基地址。 

// C++ program to print the elements of 3-D
// array using pointer notation
#include <iostream>
using namespace std;
int main()
{
int arr[2][3][2] = {
{
{5, 10},
{6, 11},
{7, 12},
},
{
{20, 30},
{21, 31},
{22, 32},
}
};
int i, j, k;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 2; k++)
cout << *(*(*(arr + i) + j) +k) << "\t";
cout <<"\n";
}
}

return 0;
}
// C program to print the elements of 3-D
// array using pointer notation
#include<stdio.h>
int main()
{
int arr[2][3][2] = {
{
{5, 10},
{6, 11},
{7, 12},
},
{
{20, 30},
{21, 31},
{22, 32},
}
};
int i, j, k;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 2; k++)
printf("%d\t", *(*(*(arr + i) + j) +k));
printf("\n");
}
}

return 0;
}

输出: 

5 10    
6 11    
7 12    
20 30    
21 31    
22 32

下图显示了上述程序中使用的 3-D 数组是如何存储在内存中的。 

下标指向数组的指针

假设arr是一个 3 行 4 列的二维数组,而ptr是一个指向 4 个整数数组的指针,而ptr包含数组arr的基地址。 

int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}};
int (*ptr)[4];
ptr = arr;

由于ptr是指向 4 个整数数组的指针,因此ptr + i将指向第 i。在取消引用ptr + i时,我们得到第 i 行的基地址。要访问第 i 行的第 j 个元素的地址,我们可以将j 添加到指针表达式*(ptr + i)中。所以指针表达式*(ptr + i) + j给出了第 i 行的第 j 个元素的地址,指针表达式* (*(ptr + i)+j)给出了第 i 行的第 j元素值. 
我们知道指针表达式 *(*(ptr + i) + j) 等价于下标表达式 ptr[i][j]。因此,如果我们有一个包含二维数组基址的指针变量,那么我们可以通过双下标该指针变量来访问数组的元素。 

// C++ program to print elements of a 2-D array
// by scripting a pointer to an array
#include <iostream>
using namespace std;

int main()
{
int arr[3][4] = {
{10, 11, 12, 13},
{20, 21, 22, 23},
{30, 31, 32, 33}
};
int (*ptr)[4];
ptr = arr;
cout << ptr<< " "<< ptr + 1<< " "<< ptr + 2 << endl;
cout << *ptr<< " "<< *(ptr + 1)<< " "<< *(ptr + 2)<< endl;
cout << **ptr<< " "<< *(*(ptr + 1) + 2)<< " "<< *(*(ptr + 2) + 3)<< endl;
cout << ptr[0][0]<< " "<< ptr[1][2]<< " "<< ptr[2][3]<< endl;
return 0;
}
// C program to print elements of a 2-D array
// by scripting a pointer to an array
#include<stdio.h>

int main()
{
int arr[3][4] = {
{10, 11, 12, 13},
{20, 21, 22, 23},
{30, 31, 32, 33}
};
int (*ptr)[4];
ptr = arr;
printf("%p %p %p\n", ptr, ptr + 1, ptr + 2);
printf("%p %p %p\n", *ptr, *(ptr + 1), *(ptr + 2));
printf("%d %d %d\n", **ptr, *(*(ptr + 1) + 2), *(*(ptr + 2) + 3));
printf("%d %d %d\n", ptr[0][0], ptr[1][2], ptr[2][3]);
return 0;
}

输出: 

0x7ffead967560 0x7ffead967570 0x7ffead967580
0x7ffead967560 0x7ffead967570 0x7ffead967580
10 22 33
10 22 33

 

这篇文章对您有用吗?