主题:[转帖]指针与数组的关系
ilpr
[专家分:420] 发布于 2005-08-25 20:12:00
指针与数组的关系
指针与数组是C语言中很重要的两个概念,它们之间有着密切的关系,利用这种关系,可以增强处理数组的灵活性,加快运行速度,本文着重讨论指针与数组之间的联系及在编程中的应用。
1.指针与数组的关系
当一个指针变量被初始化成数组名时,就说该指针变量指向了数组。如:
char str[20], *ptr;
ptr=str;
ptr被置为数组str的第一个元素的地址,因为数组名就是该数组的首地址,也是数组第一个元素的地址。此时可以认为指针ptr就是数组str(反之不成立),这样原来对数组的处理都可以用指针来实现。如对数组元素的访问,既可以用下标变量访问,也可以用指针访问。
2.指向数组元素的指针
若有如下定义:
int a[10], *pa;
pa=a;
则p=&a[0]是将数组第1个元素的地址赋给了指针变量p。
实际上,C语言中数组名就是数组的首地址,所以第一个元素的地址可以用两种方法获得:p=&a[0]或p=a。
这两种方法在形式上相像,其区别在于:pa是指针变量,a是数组名。值得注意的是:pa是一个可以变化的指针变量,而a是一个常数。因为数组一经被说明,数组的地址也就是固定的,因此a是不能变化的,不允许使用a++、++a或语句a+=10,而pa++、++pa、pa+=10则是正确的。由此可见,此时指针与数组融为一体。
3.指针与一维数组
理解指针与一维数组的关系,首先要了解在编译系统中,一维数组的存储组织形式和对数组元素的访问方法。
一维数组是一个线形表,它被存放在一片连续的内存单元中。C语言对数组的访问是通过数组名(数组的起始地址)加上相对于起始地址的相对量(由下标变量给出),得到要访问的数组元素的单元地址,然后再对计算出的单元地址的内容进行访问。通常把数据类型所占单元的字节个数称为扩大因子。
实际上编译系统将数组元素的形式a[i]转换成*(a+i),然后才进行运算。对于一般数组元素的形式:<数组名>[<下标表达式>],编译程序将其转换成:*(<数组名>+<下标表达式>),其中下标表达式为:下标表达式*扩大因子。整个式子计算结果是一个内存地址,最后的结果为:*<地址>=<地址所对应单元的地址的内容>。由此可见,C语言对数组的处理,实际上是转换成指针地址的运算。
数组与指针暗中结合在一起。因此,任何能由下标完成的操作,都可以用指针来实现,一个不带下标的数组名就是一个指向该数组的指针。
4.指针与多维数组
用指针变量可以指向一维数组,也可以指向多维数组。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。
例如,在一个三维数组中,引用元素c[i][j][k]的地址计算最终将换成:*(*(*(c+i)+j)+k)。了解了多维数组的存储形式和访问多维数组元素的内部转换公式后,再看当一个指针变量指向多维数组及其元素的情况。
1 指向数组元素的指针变量
若有如下说明:
int a[3][4];
int *p;
p=a;
p是指向整型变量的指针;p=a使p指向整型二维数组a的首地址。
*(*(p+1)+2)表示取a[1][2]的内容;*p表示取a[0][1]的内容,因为p是指向整型变量的指针;p++表示p的内容加1,即p中存放的地址增加一个整型量的字节数2,从而使p指向下一个整型量a[0][1]。
2 指向由j个整数组成的一维数组的指针变量
当指针变量p不是指向整型变量,而是指向一个包含j个元素的一维数组。如果p=a[0],则p++不是指向a[0][1],而是指向a[1]。这时p的增值以一维数组的长度为单位。
5.指针与字符数组
C语言中许多字符串操作都是由指向字符数组的指针及指针的运算来实现的。因为对于字符串来说,一般都是严格的顺序存取方式,使用指针可以打破这种存取方式,更为灵活地处理字符串。
另外由于字符串以′\0′作为结束符,而′\0′的ASCII码是0,它正好是C语言的逻辑假值,所以可以直接用它作为判断字符串结束的条件,而不需要用字符串的长度来判断。C语言中类似的字符串处理函数都是用指针来完成,使程序运行速度更快、效率更高,而且更易于理解。
回复列表 (共16个回复)
沙发
我是岳阳人 [专家分:1530] 发布于 2005-08-25 21:03:00
1 指向数组元素的指针变量
若有如下说明:
int a[3][4];
int *p;
p=a;
p是指向整型变量的指针;p=a使p指向整型二维数组a的首地址。
*(*(p+1)+2)表示取a[1][2]的内容;
这一点我也有些疑惑,我刚试了一下;
main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p;
p=a;
printf("%d\n",*(*(p+1)+2));
}
按上面的说应该结果是 第一行第二个数(7);可是却输不出来;
我把指针换换成了数组指针
main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*p)[4];
p=a;
printf("%d\n",*(*(p+1)+2));
getch();
}
得出了正确结果 "7";
我认为指向二维数组的指针是不是应该是一个数组指针呢.
板凳
ilpr [专家分:420] 发布于 2005-08-26 01:54:00
你说的对,今天特意研究了一下,把指针和数组的关系搞明白了,谢谢你
3 楼
88978289 [专家分:220] 发布于 2005-08-26 06:15:00
*p 可以 等于 a[][] 没见过?
4 楼
smflyfox [专家分:0] 发布于 2005-08-26 09:03:00
1楼的说得对。普通的指针变量如:
int *p;
此处定义的p只能指向整形变量,对于一个二维数组,比如a[3][4],单独的a代表的是行地址,如果有这样一个关系式:
p=a;
表面上看是可以的,实际上是不允许的,a是行地址,它只能付给行地址指针,否则便一起是不会让你通过的。
5 楼
我是岳阳人 [专家分:1530] 发布于 2005-08-26 11:40:00
楼主给我打了满分,我有些惭愧了.
经过思考,我发现我上面说的并不全对,撑死了只对了一半.
其实并非数组指针才能指向二维数组,由于二维数组本质上就是一个一维数组,我觉得理论上也应该可以用指向一维数组的指针指向二维数组,但此时用指针表示每个元素时,也只能表示一维数组元素的方式来表示.
如像下面的方式,我试了能通得过.
main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int i,*p;
p=a;//用一个指针变量指向二维数组.
for(i=0;i<12;i++)
printf("%d\n",p[i]);//只能用p[i]或*(p+i)这种表示一维数组的形式一个个引用,不能用a[i][j]等方式.这时的p不能代替a.如果p定义为数组指针"(*p)4",p就可以代替a.
}
上面输出的结果(1~12),是我们想要的,不过我还没有看见有谁像我这么用过.
6 楼
cracker007 [专家分:22140] 发布于 2005-08-26 13:37:00
to 楼上:
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int i,*p;
p=a;
//这么写是错误的,你过了也许是你编译器的问题。作为二维数组名,虽然和第一个元素地址一样,但实际上还是有差别。把它看成是二级指针,所以不能p=a.可以这样:int **p;p=a;或者像你一楼最后一段程序那样。
7 楼
sirfarming [专家分:1790] 发布于 2005-08-26 13:43:00
指向多维数组的指针问题
http://www.programfan.com/club/showbbs.asp?id=100710
8 楼
我是岳阳人 [专家分:1530] 发布于 2005-08-27 13:30:00
我特意下载了个Dev-C++ 4.9.9.0试了一下.
正如cracker007所说不能通过.
我先前用的是Win-tc 1.91;
9 楼
zx3cv9nm [专家分:40] 发布于 2005-08-29 14:44:00
说的好.
10 楼
kingwei [专家分:3960] 发布于 2005-08-29 16:49:00
同意6楼~~~~
我来回复