主要内容有:指针的定义,访问,操作,指针地址作为返回值,指针和引用的区别,指针和数组区别
<1>指针的定义:
一级指针定义:
int* p=NULL;
int* p=new int;
二级指针:
int **p=NULL;
int** p=new int*[10];初始化时只有最高位可先不定义
当使用const限制时,有以下几种情况:
const char* p,char const *p,char *const p,const char* const p,有何区别?
1)当const 在*前面,相当于const修饰的是*p,即指针内容:如const char* p, char const *p 则限制指针指向地址的内容不可修改
const char* p=new char('a'),则操作*p='b'会出错,不可修改指针内容
2)当const在*后面,char *const p;时,相当于const修饰的是p,即指针地址,不可修改指针的地址
char* const p=new char('a'),则p=new char('b')出错
3)两者一起则指针的内容和地址均不可改
<2>指针的访问:*(p+i), p[i];
<3>指针的操作:
char* s="AAA";
cout<<s<<endl;
s[0]='B';
cout<<s<<endl;
1)指针变量所占内存大小和指针加减有关的问题
指针变量所占内存大小:32位操作系统是32位(4字节),64位操作系统是64位(8字节);
指针变量自增自减:自增自减中指针变量值的改变大小等于所指向的对象类型的内存大小。如:char* pt1,那么pt1++就是加1,若为int* pt2,那么pt2++就是增加4。
指针运算问题都是以相应变量的类型大小作为基本单位的,例如int p[4]={0,0,0,0},p+1就是指p的地址基础上偏移4字节。同理,&p[0]+1也是一样的。除非(char*)&p[0]+1才是偏移一个字节,因为地址被强制转化为char*了。
补充:
指针所指向的对象类型判断方法——去掉指针名及和它前面的*,剩下的就是指针类型。
上面所说的地址地址++或--都是对于偏移地址offset而言的。
*p++,(*p)++,*++p,++*p有什么不同:
*和++优先级一样,采用右结合规则:
*p++,:即*(p++)结果相当于*p,因为p++返回值为p
(*p)++:先取p所指向的值,将值加1
*++p:即*(++p),结果为p下一位的值,因为++p返回值为p+1;
++*p即++(*p),结果为p的值加一
指针与sizeof()(32位系统):以下sizeof(p)的结果为:
char* p="abc" 指针大小:4
char p[] ="abc" 字符串长度,要加上字符串结束符\0:4
int* p=new int[10]; 指针大小:4
int (*p)[10]; 虽然指向数组,但还是指针:4
int* p[10]; 指针数组,本质是数组,数组的每个元素是整形指针:40
char p[10] ="abc": 10
〈5〉指针和引用的区别:
定义引用必须指明引用对象,指针则不用;
引用一旦生明则不可以修改引用对象,指针则可以修改指针的指向
引用传参不需要复制实参,指针传参需要复制实参地址
<6>指针地址作为返回值:
当指针指向全局存储区时,此时指针的地址作为返回值是有效的的,其他情况则无效。
因为函数结束是局部变量空间会被回收,全局存储区则不会
如:char* p="asda" 有效,char s[]="asda" 返回则无效
<7>指针和数组区别:
1)当数组作为函数参数时会退化为指针,即此时数组与指针操作是等价的,如:
void test(char s[],int len)
{
for (int i = 0;i < len;i++)
cout << *s++ << ' ';
}
2)其他情况,数组名可以看成一个常量指针,指向数组首元素,此时的数组名不可以进行++,--操作,不可被复制,即不可修改
注意:int a[10],a指向数组首地址,&a是数组地址,即&a+1,相当于移动40个字节,此时指针指向数组尾部。