所在的位置: C++ >> C++介绍 >> C指针解读及示例

C指针解读及示例

北京白癜风最正规的医院 http://finance.sina.com.cn/chanjing/b/20090930/09073071708.shtml

指针的概念及声明

指针是一个变量,其值为另一个变量的地址。在使用指针存储其他变量地址之前,需要先声明指针变量。指针变量声明的一般形式为:

数据类型*变量名

示例:

int*ip;//一个整型的指针,指向的类型是intdouble**dp;//一个double型的指针,指向的类型是int*float*fp;//一个浮点型的指针,指向的类型是float

特殊的指针

1、空指针

(1)空指针概念

空指针不指向任何对象,即不指向任何地址。空指针定义的方式如下:

(2)空指针生成方法

int*p1=nullptr;//这是c++11新引入的方法,nullptr是一个特殊的字面值,它可以被转换成任何其它的指针类型。

int*p2=0;

int*p=NULL,//这种是使用预处理变量的一种方式,NULL会被替换为实际值,实际值是0,所以和上边的方式是一样的。

2、野指针

(1)野指针概念

指向不可用的内存区域的指针。

(2)野指针的生成方法

指针变量未初始化:任何指针在被创建的时候,不会自动变成NULL指针,他的default值是随机的。所以一个比较好的习惯是,指针刚创建的时候,要么设置为NULL空指针,要么指向合理的内存区域。

指针释放后未置空:有时指针在free或delete后未赋值NULL,便会使人以为是合法的,此时指针指向一块未定义、未分配的内存。其实free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉,指针指向的就是“垃圾”内存。所以释放后的指针应立即将指针置为NULL,防止产生“野指针”。

指针操作超越变量作用域:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。

、空指针和野指针的区别

野指针与NULL空指针是不同的。NULL指针一般比较好判断,直接用if(p==NULL)语句判断即可。但是野指针指向的是垃圾内存区域的指针,一旦使用往往会造成不可预测的结果,这种随机不可预测的结果才是最可怕的。

指针的初始化

上边介绍了空指针和野指针,所以在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个NULL值是一个良好的编程习惯。

//方式一:初始化空指针int*p=nullptr;//方式二intq=4;int*p1=q;//方式三structStudent{inta;intb;};Student*t=newStudent();

使用new开辟的空间,记得使用delete释放,因为new出来的是返回的堆的空间,堆的空间是不会自动释放的,存放变量的栈才会自动释放。delete释放其实只是释放了申请的这块内存空间,但是指针并没有没撤销,指针还是指向这块地址,但是不可用,是非法的。所以用delete释放掉一块堆内存时,应该手动将指针设置为NULL。

指针运算符

C++提供了两种指针运算符,一种是取地址运算符,一种是间接寻址运算符*。

1、取地址运算符

是一元运算符,返回操作数的内存地址。例如,如果var是一个整型变量,则var是它的地址。可以把运算符读作"取地址运算符",这意味着,var读作"var的地址"。

intp=1;

int*q=p;//先使用运算符获取变量p的地址,再把该地址赋值给指针变量q

int**qq;//声明二级指针变量qqqq=q;//先使用运算符获取变量q的地址,再把该地址赋值给二级指针变量qq

2、间接寻址运算符*

间接寻址运算符*是运算符的补充。*是一元运算符,返回操作数所指定地址的变量的值。

intn1=*q;//先使用*运算符获取指针变量q所指向的变量(即p),再用该变量(p)初始化变量n1

综合示例:

#includeiostreamusingnamespacestd;constintMAX=;intmain(){intp=1;int*q=p;int**qq=q;coutqqendl;cout**qqendl;}

运行结果

指针的算术运算

1、指针支持四种算术运算:++、--、+、-

假设ptr是一个指向地址的整型指针,是一个2位的整数,对该指针执行下列的算术运算:

ptr++

在执行完上述的运算之后,ptr将指向位置,因为ptr每增加一次,它都将指向下一个整数位置,即当前位置往后移4个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果ptr指向一个地址为的字符,上面的运算会导致指针指向位置,因为下一个字符位置是在。

示例1:递增指针

#includeiostreamusingnamespacestd;constintMAX=;intmain(){intvar[MAX]={10,,};int*ptr;//指针中的数组地址ptr=var;for(inti=0;iMAX;i++){coutptrendl;cout*ptrendl;//移动到下一个位置ptr++;}return0;}

运行结果

示例2:递减指针

#includeiostreamusingnamespacestd;constintMAX=;intmain(){intvar[MAX]={10,,};int*ptr=var[MAX-1];//指针中最后一个元素的地址for(inti=MAX;i0;i--){cout*ptrendl;//移动到下一个位置ptr--;}return0;}

运行结果

2、指针支持关系运算符进行比较,如==、和

#includeiostreamusingnamespacestd;constintMAX=;intmain(){intarr[2]={10,2};int*p=arr;//指针中第一个元素地址if(p=arr[1]){cout*pendl;}else{coutarr[1]endl;}return0;}

运行结果

指针内存大小

可以使用函数sizeof(指针的类型)计算指针本身占了多大的内存。

coutsizeof(int*)endl;coutsizeof(float*)endl;coutsizeof(double*)endl;coutsizeof(char*)endl;

指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。

指针表达式

如果一个表达式的结果是一个指针,那么这个表达式就叫指针表达式。如:

intmain(){inta,b;intarray[10];int*pa;pa=a;//a是一个指针表达式。int**ptr=pa;//pa也是一个指针表达式。*ptr=b;//*ptr和b都是指针表达式。pa=array;pa++;//这也是指针表达式。}

指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。当一个指针表达式的结果指针具有指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。

const修饰指针

1、常量指针:const修饰指针

2、指针常量:const修饰常量

、既修饰常量又修饰指针

#includeiostreamusingnamespacestd;intmain(){inta=10;intb=10;//const修饰的是指针,指针指向可以改,指针指向的值不可以更改constint*p1=a;p1=b;//正确//*p1=;报错//const修饰的是常量,指针指向不可以改,指针指向的值可以更改int*constp2=a;//p2=b;//错误*p2=;//正确//const既修饰指针又修饰常量,都不可以改constint*constp=a;//p=b;//错误//*p=;//错误return0;}

指针和数组关系

利用指针访问数组:

#includeiostreamusingnamespacestd;intmain(){intarr[5]={1,2,,4,5};int*p=arr;coutarr[0]endl;cout*pendl;//指针遍历数组for(inti=0;isizeof(arr)/sizeof(int);i++){cout*p"";p++;}}

运行结果

指针和函数关系

利用指针改换值。

#includeiostreamusingnamespacestd;intmain(){inta=10;intb=20;swap(a,b);//运行结果进行了交换cout"a="a"b="bendl;return0;}voidswap(int*a,int*b){inttemp=*a;*a=*b;*b=temp;}

运行结果


转载请注明:http://www.aierlanlan.com/rzfs/6189.html