【c++】指针
一. 指针的概念
二. 指针和指针变量
三. 指针和数组
四.指针和字符串
参考:
《c++从入门到精通》 人民邮电出版社
深度长文教你彻底掌握C++/C指针
https://blog.csdn.net/xierhacker/article/details/52516742
C++指针:指针变量、数组指针、字符串指针、函数指针(西电)
http://c.biancheng.net/cpp/biancheng/cpp/rumen_6/(很好很详细)
一. 指针的概念
计算机内存地址:
为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。
如果在程序中定义了一个变量,在编译时就给这个变量分配内存单元。系统根据程序中定义的变量类型,分配一定长度的空间。例如,C++编译系统一般为整型变量分配4个字节,为单精度浮点型变量分配4个字节,为字符型变量分配1个字节。内存区的每一个字节有一个编号,这个编号就是“地址”。
请务必弄清楚一个内存单元的地址与内存单元的内容这两个概念的区别。在程序中一般是通过变量名来对内存单元进行存取操作的。其实程序经过编译以后已经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。这种按变量地址存取变量值的方式称为直接存取方式,或直接访问方式。
指针的概念:
如果有一个变量是专门用来存放另一变量地址(即指针)的,则它称为指针变量。指针变量的值(即指针变量中存放的值)是地址(即指针)。
如上图所示,i_pointer为指针,它所存储的值(2000)是一个地址,这个地址中存储的值是i (i=3),所以i_pointer所指向的值是3。
二. 指针和指针变量
定义指针变量:
int *p; //定义一个指针变量p,为整型,表示它所指向的值是一个整型。 int i=3; p=&i; //p中存放的是一个地址(整型变量i的地址)
第1行定义一个整型指针变量p,表示它所指向的值是一个整型(i)。第三行将i的地址给了p,这是因为指针中存放的值是一个地址。
看一个例子:
#include<iostream> #include<stdio.h> using namespacestd; int main(intargc,char *argv[ ]) { int *p1,*p2; int i=3; int j=5; p1=&i; p2=&j; cout<<"i的值:"<<i<<endl; cout<<"i的地址:"<<&i<<endl; cout<<"p1中存储的地址:"<<p1<<endl; cout<<"p1所指向的值:"<<*p1<<endl; cout<<"j的值:"<<j<<endl; cout<<"j的地址:"<<&j<<endl; cout<<"p2中存储的地址:"<<p2<<endl; cout<<"p2所指向的值:"<<*p2<<endl; cout<<endl; cout<<"p1的地址&p1:"<<&p1<<endl; cout<<"&*p1的值为:"<<&(*p1)<<endl; cout<<endl; cout<<"p2的地址&p2:"<<&p2<<endl; cout<<"&*p2的值为:"<<&(*p2)<<endl; cout<<endl; cout<<"*(p1-1)的值为:"<<*(p1-1)<<endl; cout<<"*p1+1 的值为:"<<*p1-1<<endl; return 0; }
运行结果:
分析指针存储的内容和指针指向的内容:
p1=&i, 由此可知,p1中存储的值是i的地址,即p1指向i。
p2=&j, 由此可知,p2中存储的值是j的地址,即p2指向j。
分析各变量和指针变量的地址:
地址 |
该地址存放的值 |
0x6cfecc |
P1 |
0x6cfec8 |
P2 |
0x6cfec4 |
i |
0x6cfec0 |
j |
p1、p2、i、j依次被定义,他们在内存中占用连续的存储单元,且这四个变量在栈中是向低地址扩展的存储空间(注意:这里是栈,如果换成堆就不同了,是向高地址扩展的)。又因为int型占用4个字节,所以p1、p2、i、j的存储地址依次减4。
区分以下二者的不同:
*(p1-1)
*p1-1
这二者的区别:前者*(p1-1)是p1中存放的值(i的地址)减去一个地址单位,即0x6cfec4 - 4=0x6cfec0,即表示i的地址减4,刚好为j的地址,所以*(p1-1)表示j的值。后者*p1-1是先*p1再-1,即i的值–1。
三. 指针和数组
变量有指针,数组也有指针,这是因为数组的每个元素占用不同的存储单元,即他们有不同的地址,有不同的指针。
指针和一维数组
指针和数组的联系:对于一个数组来说,数组的名字就是这个数组的首地址,即该数组首个元素的指针。
int array[10]; int *p; p=array; // 将array首元素的地址给p
注意:对于一个数组来说,数组的名称=数组的首地址=数组首个元素的地址!所以,p=array,相当于p=&array[0]。
这样,要访问数组中的第i个元素,有两种方式:
1. 通过访问数组元素下标,例 array[i]
2. 通过访问数组元素的指针实现,例*(array+i)或*(p+i)
编程实例运用:
//指针和一维数组.cpp #include<iostream> using namespace std; int main() { int array[10]; int *p; p=array; //或者p=&array[0]; for(int i=0;i<10;i++) array[i] =i; //通过指针打印数组 cout<<"通过指针打印数组: "<<endl; for(int i=0;i<10;i++) cout<<*(p+i)<<""; cout<<endl; //通过数组下标打印数组 cout<<"通过数组下标打印数组: "<<endl; for(int i=0;i<10;i++) cout<<*(array+i)<<""; cout<<endl; return 0; }
运行结果:
指针和多维数组:
用指针变量不仅可以指向一维数组,也可以指向多维数组。先定义一个二维数组array,并初始化,如下:
注意:一个*等同于一个[ ],所以 *(array+1)+2 == (& array[1][2] ) 即表示第i行第j列的元素的地址。所以array[1][2]==*( *(array+1)+2)。
int array[2][3]={{11,12,13},{21,22,23}}; int **p;
使用指针访问二维数组的元素:
//指针和多维数组.cpp #include<iostream> using namespace std; int main() { intarray[2][3]={11,12,13,21,22,23}; int *p; // 或者 (*p)[3] 注意优先级顺序 p=array[0]; //p指向数组array的首地址 cout<<"使用指针访问二维数组的元素:"<<endl; for(int i=0;i<2;i++) { for(intj=0;j<3;j++) { cout<<*(p+3*i)+j<<" "; } } cout<<endl; return 0; }
运行结果:
分析:p=array[0] 等价于p=&array[0][0] 。那如果写成p=array呢?会显示错误:
这是因为 array是一个二维数组名,相当于指针的指针,而p只是一个指针,二者不符。分析一下为什么array是指针的指针?从值的角度来考虑,array等价于&array[0],array[0]等价于&array[0][0],所以array == &(&array[0][0]),所以array是指针的指针。虽然p和array的值相等,但二者在概念上是不同级别的。所以p=array //错误!
区分指针数组和数组指针:
指针数组是指数组中存放的是指针类型的元素。例 char *p[2] ; //指针数组p,p中存放了两个指针型元素
char *p[2] ; //指针数组p,p中存放了两个指针型元素 char array[2][3]; p[0]=array[0]; p[1]=array[1];
数组指针:指针用来指向一个数组。
int (*p)[10]; //表示指针p用来指向含有10个元素的整型数组。
例:
intarray[2][3]={11,12,13,21,22,23}; int (*p)[3] ; //表示p指向一个含有3个元素的数组 p=array;
分析:
p[0]==&array[0], 表示第0行元素的地址
p[1]==&array[1], 表示第1行元素的地址
四.指针和字符串
字符串相当于字符数组,注意:字符串以‘\0’结尾。
char str[10]=”hello word” char *p; p=str; //将str的首地址传给p,即指针p指向了字符串的开头位置。
编程实例:
//指针和字符数组.cpp #include<iostream> using namespace std; int main() { charstr[10]="hello"; char *p; p=str; for(inti=0;str[i]!='\0';i++) cout<<*(p+i); cout<<endl; return 0; }
应用:实现字符串复制函数
//指针和字符数组.cpp #include<iostream> using namespace std; void copy_str(char *p1,char *p2) { while(*p1!='\0') { *p2=*p1; p1++; p2++; } *p2='\0'; } int main() { char str1[20]="hello world"; char str2[20]; copy_str(str1,str2); for(int i=0;str2[i]!='\0';i++) cout<<*(str2+i); cout<<endl; return 0; }
运行结果:
------------------------------------------- END -------------------------------------