指针与数组
来源:互联网 发布:程序员的思维 编辑:程序博客网 时间:2024/06/15 15:48
1.“指针”是个地址的概念。它本身不是变量,并不分配存储单元,仅表示对象在内存中的地址。
2.数组名同时也是该数组首元素的地址,数组名为地址常量,对该地址进行增减运算来移动指针寻找其他的数组元素,而不是对指针变量进行加减操作。
例:
#include<stdio.h>
int main(void)
{
int a[3]={1,2,3};
int *p=a; // p为指向a的首元素地址的指针变量
printf(“a=%p\n",a); // a表示数组a[3]的首元素地址,为常量
printf(&a[0]=%p\n",&a[0]); // &a[0]的意义与a相同
printf(”&a+1=%p\n",a+1); // 对a进行增量运算,移动指针使其指向a[1]
printf("&a[0]+1=%p\n",&a[0]+1); // &a[0]+1与a+1意义相同
printf("&a=%p\n",&a); // &a的值与a相同,但指向的是整个数组单元
printf(”&a+1=%p\n",&a+1); // 对&a移动1,则&a+1指向的是数组末单元下一个单元的地址
return 0;
}
运行结果:
a=0x7ffe7de5c4a0
&a[0]=0x7ffe7de5c4a0
a+1=0x7ffe7de5c4a4
&a[0]+1=0x7ffe7de5c4a4
&a=0x7ffe7de5c4a0
&a+1=0x7ffe7de5c4ac
说明:尽管a=&a=&a[0],但它们三个都不是变量,更谈不上是同类型的变量,因此可以取值相同但 意义不同,从而进行指针移动时变动大小也可以不同
a是数组首元素的首地址,&a是整个数组的首地址。
—————————————————————————
3. 指向整型指针的指针
先看如下示例:
2 using namespace std;
3
4 int main()
5 {
6 int a[5] = {1, 2, 3, 4, 5};
7 int *p = a;
8 int **point = &p;
9
10 cout << "a = " << a << endl
11 << "p = " << p << endl
12 << "&p = " << &p << endl
13 << "point = " << point << endl
14 << "&point = " << &point << endl;
15
16 for (int i = 0; i < 5; i++)
17 {
18 cout << "&a[" << i << "] = " << &a[i] << endl;
19 }
20 return 0;
21 }
运行结果图如下:
我们先看下内存分配图:
从上图可以看出point指针中存放的是p指针的地址,而p指针中存放的是a[0]的地址。所以*point和p是一样的,前者是取point指针中存放的地址(0025F754)中的值,即取地址0025F754中存放的值(0025F760),而后者就是0025F760,所以两者是等价的。**point和a[0]是等价的,前者可以写成*p,*p是取p中存放的地址(0025F760)中的值,即地址0025F760中存放的值1。由上可以得出*point等于p, **point 等于 a[0]。通过上图可以清晰的对付诸如*point++等问题。
————————————————————————————
4. 二维数组的指向整型指针的指针
先看如下示例:
2 using namespace std;
3
4 int main()
5 {
6 char *a[] = {"Wel", "To", "China"};
7 char **p = a;
8 for(int i = 0; i < 3; i++)
9 {
10 for (int j = 0; j < strlen(a[i]) + 1; j++)
11 {
12 cout << a[i][j] << "\t" << (void *)&a[i][j] << endl;
13 }
14 cout << endl;
15 }
16
17 for (int i = 0; i < 3; i++)
18 {
19 cout << "a[" << i << "] = " << (void *) a[i] << endl
20 << "&a[" << i << "] = " << &a[i] << endl;
21 }
22
23
24 cout << "p = " << p << endl
25 << "&p = " << &p << endl;
26 return 0;
27 }
运行结果图如下:
我们先看下内存分配图:
————————————————————————
5.二维数组和指针
以前一直有种误解:
二维数组的是数组的数组,所以数组的首地址是指向第一个元素指针,而这个元素又是一个数组,所以把数组首地址理解为指向指针的指针。
如int a[3][2];,以前一直认为a是一个指向int指针的指针,即是一个int**。最近发现这是错的。
如果int **p=a; 编译就会报错。如果强制转换int **p=(int **)a,则使用p[i][j]访问数组元素时出错。
首先,因为a的定义为 int a[3][2];则a的类型是int* [3][2]数组类型,或者int* [][2],即指向大小为2的数组的指针,类型与int **不同,所以int **p=a;出错
说明:二维数组的数组名为一个二级指针常量,实际上是一个行指针
进一步讨论:
设有整型二维数组a[3][4]如下:
0 1 2 3
4 5 6 7
8 9 10 11
它的定义为:
int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}
设数组a的首地址为1000,各下标变量的首地址及其值如图所示。
![](http://c.biancheng.net/cpp/uploads/allimg/120129/1212423sdafssda.gif)
前面介绍过,C语言允许把一个二维数组分解为多个一维数组来处理。因此数组a可分解为三个一维数组,即a[0]、a[1]、a[2]。每一个一维数组又含有四个元素。
![](file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_image002.gif)
![](http://c.biancheng.net/cpp/uploads/allimg/120129/qwfd423vsds.gif)
例如a[0]数组,含有a[0][0],a[0][1],a[0][2],a[0][3]四个元素。
数组及数组元素的地址表示如下:从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组0行的首地址,等于1000。a+1代表第一行的首地址,等于1008。如图:
![](http://c.biancheng.net/cpp/uploads/allimg/120129/adsws3453rgtrt.gif)
![](file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.gif)
a[0]是第一个一维数组的数组名和首地址,因此也为1000。*(a+0)或*a是与a[0]等效的, 它表示一维数组a[0]0 号元素的首地址,也为1000。&a[0][0]是二维数组a的0行0列元素首地址,同样是1000。因此,a,a[0],*(a+0),*a,&a[0][0]是相等的。
同理,a+1是二维数组1行的首地址,等于1008。a[1]是第二个一维数组的数组名和首地址,因此也为1008。&a[1][0]是二维数组a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。
由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。
此外,&a[i]和a[i]也是等同的。因为在二维数组中不能把&a[i]理解为元素a[i]的地址,不存在元素a[i]。C语言规定,它是一种地址计算方法,表示数组a第i行首地址。由此,我们得出:a[i],&a[i],*(a+i)和a+i也都是等同的。
另外,a[0]也可以看成是a[0]+0,是一维数组a[0]的0号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。
![](file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_image004.gif)
由a[i]=*(a+i)得a[i]+j=*(a+i)+j。由于*(a+i)+j是二维数组a的i行j列元素的首地址,所以,该元素的值等于*(*(a+i)+j)。
【例10-22】
- main(){
- int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
- printf("%d,",a);
- printf("%d,",*a);
- printf("%d,",a[0]);
- printf("%d,",&a[0]);
- printf("%d\n",&a[0][0]);
- printf("%d,",a+1);
- printf("%d,",*(a+1));
- printf("%d,",a[1]);
- printf("%d,",&a[1]);
- printf("%d\n",&a[1][0]);
- printf("%d,",a+2);
- printf("%d,",*(a+2));
- printf("%d,",a[2]);
- printf("%d,",&a[2]);
- printf("%d\n",&a[2][0]);
- printf("%d,",a[1]+1);
- printf("%d\n",*(a+1)+1);
- printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
- }
- 指针:指针与数组
- 指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 数组指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组 与数组指针
- 指针数组与数组指针
- 数组指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- HDCP
- 搭建git服务器[linux环境]
- iOS 拨打电话 发送短信
- 关于程序内存的深度理解
- windows下使用winpcap-1.环境安装
- 指针与数组
- ACM:数论专题(1)——素数的判定
- 初学android开发--day02
- html5 div 简单布局
- 6轴传感器LSM330DLC的底层驱动
- Apache视频教程
- 10.公比
- BufferedInputStream的read方法原理
- android中的线性布局