C++数组和指针用法详解(附带实例)
C++ 中,数组作为同名、同类型元素的有序集合,被顺序存放在一块连续的内存中,且每个元素的存储空间大小相同。数组中第一个元素的存储地址就是整个数组的首地址,该地址存放在数组名中。
一维数组的结构是线性的,数组元素按下标值由小到大的顺序依次存放在一块连续的内存中。二维数组以矩阵方式,先行后列依次存放各元素,在内存中仍然是线性结构。
例如:

图 1 将指针指向一维数组
通过首地址和偏移量,可以定位任意一个数组元素。
【实例 1】指针与一维数组。通过指针变量输出数组中的各元素。具体代码如下:
因此,可以将实例 1 中的第 9 行代码修改如下:
还可以将第 10~11 行代码修改如下,程序运行效果一样:
通过指针和自增、自减运算操作数组的说明如下:

图 2 二维数组元素的存储情况
可见,二维数组在内存中仍然是线性结构。
将二维数组的首地址赋给指针变量,同样可以通过指针引用数组元素,进行各类操作。例如:
【实例 2】使用指针遍历二维数组。本实例中,将二维数组的首地址赋给指针,然后使用指针自增输出数组元素。代码如下:
函数名 a 本质上也是一个指向数组的指针,因此通过偏移可以表示任意一行(如 a+m)或任意一个元素(如 (a+m)+n)的地址。
【实例 3】使用数组名和偏移输出二维数组。利用数组名和偏移对二维数组进行输出,具体代码如下:
字符数组就是一个字符串,通过字符指针可以指向一个字符串。例如:
【实例 4】连接两个字符串。本实例中不使用处理字符串函数 strcat(),通过指针偏移连接两个字符串,具体代码如下:
一维数组的结构是线性的,数组元素按下标值由小到大的顺序依次存放在一块连续的内存中。二维数组以矩阵方式,先行后列依次存放各元素,在内存中仍然是线性结构。
C++指针与一维数组
指针是存放地址的变量,如果把数组的首地址赋给指针,就可以通过指针引用数组元素。例如:
int a[8]; //定义一个整型数组a,包含8个元素 int *p; //定义一个整型指针p p=&a[0]; //将数组的首地址赋给p此时,p 指向数组的首地址,也就是 a[0] 元素,p+1 指向 a[1] 元素,p+2 指向 a[2] 元素,以此类推,p+7 指向 a[7] 元素,如下图所示。

图 1 将指针指向一维数组
通过首地址和偏移量,可以定位任意一个数组元素。
【实例 1】指针与一维数组。通过指针变量输出数组中的各元素。具体代码如下:
#include <iostream> using namespace std; int main() { int i,a[10]; int *p; for(i=0;i<10;i++) //for 循环,为数组元素赋值 a[i]=i; p=&a[0]; //将 a[0]元素的地址赋给p,也就是将数组的首地址赋给p for(i=0;i<10;i++,p++) //for 循环,通过指针输出数组元素 cout << *p << endl; }程序运行结果为:
0
1
2
3
4
5
6
7
8
9
因此,可以将实例 1 中的第 9 行代码修改如下:
p = a; // 将数组的首地址赋给 p
还可以将第 10~11 行代码修改如下,程序运行效果一样:
for(i=0;i<10;i++) //for 循环,通过*(a+i)输出数组元素 cout << *(a+i) << endl;
通过指针和自增、自减运算操作数组的说明如下:
- *(p--) 相当于 a[i--],先对 p 进行“*”运算,再使 p 自减;
- *(++p) 相当于 a[++i],先使 p 自增,再进行“*”运算;
- *(--p) 相当于 a[--i],先使 p 自减,再进行“*”运算。
C++指针与二维数组
二维数组中各元素在内存中的存储情况如下图所示:
图 2 二维数组元素的存储情况
可见,二维数组在内存中仍然是线性结构。
将二维数组的首地址赋给指针变量,同样可以通过指针引用数组元素,进行各类操作。例如:
int a[4][3]; //声明一个二维数组a int *p; //声明一个指针p p=a[0]; //将数组的首地址赋给指针p二维数组中,a、a[0]、&a[0][0] 都可以表示数组的首地址,只要将该地址赋给指针变量,就可以使用指针操作二维数组中的元素。
【实例 2】使用指针遍历二维数组。本实例中,将二维数组的首地址赋给指针,然后使用指针自增输出数组元素。代码如下:
#include <iostream> #include <iomanip> using namespace std; int main() { int a[4][3]={1,2,3,4,5,6,7,8,9,10,11,12}; //定义二维数组a并初始化 int *p; //定义指针p p=a[0]; //将数组的首地址赋给指针 for(int i=0;i<sizeof(a)/sizeof(int);i++) //for 循环,循环次数为数组元素,感受二维数组的线性存储结构 { cout <<"address:"; cout << p; //输出当前数组元素的地址 cout << " is "; cout << *p++ << endl; //使用指针输出数组元素的值 } }程序运行结果为:
address:0x6ffde0 is 1
address:0x6ffde4 is 2
address:0x6ffde8 is 3
address:0x6ffdec is 4
address:0x6ffdf0 is 5
address:0x6ffdf4 is 6
address:0x6ffdf8 is 7
address:0x6ffdfc is 8
address:0x6ffe00 is 9
address:0x6ffe04 is 10
address:0x6ffe08 is 11
address:0x6ffe0c is 12
- a、a[0]、&a[0][0] 均可表示数组的首地址。其中,a[0] 还表示数组第 1 行的首地址,&a[0][0] 还表示第 1 行 1 列元素的地址;
- a[m]、a+m 均可表示数组第 m+1 行的首地址;
- a[0]+n、&a[0][n] 均表示数组第 1 行第 n+1 个元素的地址,a[m]+n、&a[m][n] 表示数组 m+1 行第 n+1 个元素的地址;
- a[m][n]、*(a[m]+n) 和 *(*(a+m)+n) 均表示数组第 m+1 行 n+1 列元素。
函数名 a 本质上也是一个指向数组的指针,因此通过偏移可以表示任意一行(如 a+m)或任意一个元素(如 (a+m)+n)的地址。
【实例 3】使用数组名和偏移输出二维数组。利用数组名和偏移对二维数组进行输出,具体代码如下:
#include <iostream> using namespace std; int main() { int i,j; int a[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}}; //定义二维数组a并初始化 cout << "the array is: " << endl; //双重 for 循环,遍历该数组 for(i=0;i<4;i++) { for(j=0;j<3;j++) cout << *(*(a+i)+j) << endl; //使用*(*(a+i)+j)方式输出数组元素 } }程序运行结果为:
the array is:
1
2
3
4
5
6
7
8
9
10
11
12
C++指针与字符数组
使用指针可以引用字符数组。这样的指针称为字符指针,它指向的是字符型内存空间。其定义形式如下:char *p;
字符数组就是一个字符串,通过字符指针可以指向一个字符串。例如:
char *string; string="c.biancheng.net";
【实例 4】连接两个字符串。本实例中不使用处理字符串函数 strcat(),通过指针偏移连接两个字符串,具体代码如下:
#include <iostream> using namespace std; int main() { char str1[50],str2[30],*p1,*p2; //让两个指针分别指向两个数组 p1=str1; p2=str2; cout << "please input string1:" << endl; //给 str1 赋值 gets(str1); cout << "please input string2:" << endl; //给 str2 赋值 gets(str2); while(*p1!='\0') //把 p1 移动到 str1 的末尾 p1++; while(*p2!='\0') //取 p2 指向的值赋给 p1 指向的地址(str1 的末尾),即连接 str1 和 str2 *p1++=*p2++; *p1='\0'; cout << "the new string is:" << endl; //输出新的 str1 puts(str1); }程序运行结果为:
please input string1:
c.biancheng
please input string2:
.net
the new string is:
c.biancheng.net