一.概述:
如果指针存储了某个变量的地址,我们就可以说指针指向这个变量.
数组的存储是连续的,数组名就是数组的地址,这样一来数组和指针就有着很微妙的关系。
二.指针数组
int a[] = {1,2,3}; //数组名就是数组的地址. int *p = &a[0]; //等价于 *p=a;
printf("len=%lu\n",sizeof(int));//64位环境下取得int长度为4 //指针加1代表地址向后挪动所指向类型的长度位+4(这里类型是int,长度为4) //也就是说p指向a[0],p+1指向a[1],以此类推,所以我们通过指针也可以取出数组元素 for(int i=0;i<3;++i){ //printf("a[%d]=%d\n",i,a[i]); printf("a[%d]=%d\n",i,*(p+i));//由于a就代表数组的地址,其实这里还可以写成*(a+i),但是注意这里*(p+i)可以写成*(p++),但是*(a+i)不能写成*(a++),因为数组名是常量 }
1.假设a[0]的地址是ffc1,这里 p+1则代表着 p 的值加4的长度,那么a[1]的地址就是ffc5, p+i代表的是a[i]的地址。p+1不一定代表着p的值加4,加多少取决于数组类型.
2.*(p++)其实就是相当于p = p + 1,直接修改了p值,而且每次是加4。因此,每执行一次p++,指针p就会指向下一个数组元素.
注意:
*(a++)相当于a=a+1; 刚刚也说了,这种方式相当修改了a的地址,数组名a是个常量!不能进行赋值运算。
补充:
++i 与 i++ 的区别:
(1)如果只是看i++和++i,这两个是等价的,都等同于i=i+1,都是变量自身加1。
(2)在一般情况下,它们都是跟赋值联系在一起。
比如:
int a,i=0;
a=i++;//将i的值赋值给a,即a=i;然后再执行i=i+1;
也就是【a=i++;】与【a=i; i=i+1;】等价。
a=0;i=1
a=++i;//将i+1的值赋给a,即a=i+1;然后再执行i=i+1;
也就是【a=++i;】与【a=i+1;i=i+1;】等价。
a=1,i=1;
(3)【总结一下】①前置++是将自身加1的值赋值给新变量,同时自身也加1;
②后置++是将自身的值赋给新变量,然后才自身加1.
从上面的例子我们可以得出如下结论:
1.数组名a==&a[0]==*p;2.如果p指向一个数组,那么p+1指向数组的下一个元素,同时注意p+1移动的长度并不固定,具体需要根据p指向的数组的数据类型而定;
3.指针可以写成p++形式,但是数组名不可以,因为数组名是常量。
三.指针字符串
char a[] = "xb"; *a ='X'; printf("%s",a)
结果就是:Xb
char *s = "xb"; *s = "like";
两种错误:
1.*s = "like" 相当于把字符串"like"存进s指向的那一块内存空间,
char *s="xb", s指向的是"xb"的首字符'x',也就是说*s指向的一块char类型的存储空间,只有1个字节,要"like"存进1个字节的空间内,肯定内存溢出
2.因为s指向的一个常量字符串,不允许修改它内部的字符。
char a[] = "lmj";定义的是一个字符串变量!