彻底搞定C语言指针 第四篇
副标题#e#
1 int i 说起
你知道我们申明一个变量时象这样int i ;这个i是大概在它处从头变赋值的。 如下:
int i=0;
//…
i=20;//这里从头赋值了
不外有一天我的程 序大概需要这样一个变量(暂且称它变量),在申明时就赋一个初始值。之后我的措施在其它任那里都 不会再去从头对它赋值。那我又应该怎么办呢?用const .
//**************
const int ic =20;
//…
ic=40;//这样是不行以的,编译时是无法通过,因为我们不能对 const 修饰的ic从头赋值的。
//这样我们的措施就会更早更容易发明问题了。
//**************
有了const修饰的ic 我们不称它为变量,而称标记常量,代表着20这 个数。这就是const 的浸染。ic是不能在它处从头赋新值了。
认识了const 浸染之后,别的,我 们还要知道名目标写法。有两种:const int ic=20;与int const ic=20;。它们是完全沟通的。这一 点我们是要清楚。总之,你务须要记着const 与int哪个写前都不影响语义。有了这个观念后,我们来看 这两个家伙:const int * pi与int const * pi ,按你的逻辑看,它们的语义有差异吗?呵呵,你只要 记着一点,int 与const 哪个放前哪个放后都是一样的,就比如const int ic;与int const ic;一样 。也就是说,它们是沟通的。
好了,我们此刻已经搞定一个“双包胎”的问题。那么 int * const pi与前两个式子又有什么差异呢?我下面就来详细阐明它们的名目与语义吧!
2 const int * pi的语义
我先来说说const int * pi是什么浸染 (虽然int const * pi也是一样 的,前面我们说过,它们实际是一样的)。看下面的例子:
//*************代码开始 ***************
int i1=30;
int i2=40;
const int * pi=&i1;
pi=&i2; //4.留意这里,pi可以在任意时候从头赋值一个新内存地点
i2=80; //5.想想看:这里能用*pi=80;来取代吗?虽然不能
printf( “%d”, *pi ) ; //6. 输出是80
//*************代码竣事***************
语义阐明:
看出来了 没有啊,pi的值是可以被修改的。即它可以从头指向另一个地点的,可是,不能通过*pi来修改i2的值。 这个法则切合我们前面所讲的逻辑吗?虽然切合了!
首先const 修饰的是整个*pi(留意,我 写的是*pi而不是pi)。所以*pi是常量,是不能被赋值的(固然pi所指的i2是变量,不是常量)。
其次,pi前并没有用const 修饰,所以pi是指针变量,能被赋值从头指向另一内存地点的。你可 能会疑问:那我又如何用const 来修饰pi呢?其实,你留意到int * const pi中const 的位置就或许可 以大白了。请记着,通过名目看语义。哈哈,你大概已经看出了纪律吧?那下面的一节也就没须要看下 去了。不外我还得继承我的战斗!
3 再看int * const pi
确实,int * const pi与前面 的int const * pi会很容易给夹杂的。留意:前面一句的const 是写在pi前和*号后的,而不是写在*pi 前的。很显然,它是修饰限定pi的。我先让你看例子:
//*************代码开始 ***************
int i1=30;
int i2=40;
int * const pi=&i1;
//pi=&i2; 4.留意这里,pi不能再这样从头赋值了,即不能再指向另一个新地点。
//所以我已经注释了它。
i1=80; //5.想想看:这里能用*pi=80;来取代吗?可以,这 里可以通过*pi修改i1的值。
//请自行与前面一个例子较量。
printf( “% d”, *pi ) ; //6.输出是80
//***************代码竣事 *********************
语义阐明:
看了这段代码,你大白了什么?有没有发明 pi值是不能从头赋值修改了。它只能永远指向初始化时的内存地点了。相反,这次你可以通过*pi来修改 i1的值了。与前一个例子比较一下吧!看以下的两点阐明
1)pi因为有了const 的修饰,所以只 是一个指针常量:也就是说pi值是不行修改的(即pi不行以从头指向i2这个变量了)(看第4行)。
2)整个*pi的前面没有const 的修饰。也就是说,*pi是变量而不是常量,所以我们可以通过 *pi来修改它所指内存i1的值(看5行的注释)
#p#副标题#e#
总之一句话,这次的pi是一个指向int变量范例数 据的指针常量。
我最后总结两句:
1) 假如const 修饰在*pi前则不能改的是*pi(即不能 雷同这样:*pi=50;赋值)而不是指pi.
2) 假如const 是直接写在pi前则pi不能改(即不能雷同 这样:pi=&i;赋值)。
请你务必先记着这两点,相信你必然不会再被它们给搞糊了。此刻 再看这两个申明语句int const *pi和int * const pi时,呵呵,你会头昏脑胀照旧很轻松惬意?它们各 自申明的pi别离能修改什么,不能修改什么?再问问本身,把你的领略汇报我吧,可以发帖也可以发到 我的邮箱(我的邮箱[email protected])!我必然会复原的。
3) 增补三种环境。
这里, 我再增补以下三种环境。其实只要上面的语义搞清楚了,这三种环境也就已经被包括了。不外作为三种 详细的形式,我照旧简朴提一下吧!
环境一:int * pi指针指向const int i常量的环境
#p#分页标题#e#
//**********begin*****************
const int i1=40;
int *pi;
pi=&i1; //这样可以吗?不可,VC下是编译错。
//const int 范例的i1的地点 是不能赋值给指向int 范例地点的指针pi的。不然pi岂不是能修改i1的值了吗!
pi=(int* ) &i1; // 这样可以吗?强制范例转换但是C所支持的。
//VC下编译通过,可是仍 不能通过*pi=80来修改i1的值。去试试吧!看看详细的奈何。
//***********end***************
环境二:const int * pi指针指向const int i1的 环境
//*********begin****************
const int i1=40;
const int * pi;
pi=&i1;//两个范例沟通,可以这样赋值。很显然,i1的值无论是通过pi照旧i1都不能修 改的。
//*********end*****************
环境三:用const int * const pi申明 的指针
//***********begin****************
int i
const int * const pi=&i;//你能想象pi可以或许作什么操纵吗?pi值不能改,也不能通过pi修改i的值。因为不管是*pi还 是pi都是const的。
//************end****************
下篇预告:函数参数的 指针通报,值通报,引用通报 疑惑(觉得a,b已经取代了x,y,对x,y的操纵就是对a,b的操纵了,这 是一个错误的概念啊!)。