本文主要介绍一个介绍性的例子来说明C语言程序设计中的指针赋值,并通过const int i和int *const pi两个例子来分析指针赋值和地址指向。有需要的朋友可以参考一下。
从const 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
和前两种说法有什么不同?我们来详细分析一下它们的格式和语义。
先说const int *pi的作用(当然int const *pi也是一样的。我们前面说过,它们其实是一样的)。请看下面的例子:
#include 'stdio.h '
主()
{
/*代码开始*/
int i1=30
int i2=40
/*现在pi变量的内容是i1的内存地址*/
const int * pi=i1
/*注意pi可以在任何时候重新分配一个新的内存地址*/
/* PI变量的内容是i2的内存地址*/
pi=i2
/*想一想:这里可以用*pi=80代替吗?当然不是!*/
i2=80
printf('%d\n ',* pi);/*输出为80 */
/*代码结束*/
}
语义分析:
看,圆周率的值是可以修改的。也就是说,它可以被重定向到另一个地址,但是i2的值不能被*pi修改。这个规律符合我们之前讲的逻辑吗?当然合适。
首先const修饰了整个*pi(注意我写的是*pi而不是pi)。所以*pi是常数,不能赋值(虽然pi所指的i2是变量,不是常数)。
其次,pi前面没有用const修饰,所以pi是一个指针变量,可以赋值指向另一个内存地址。你可能会想:那我怎么用const修改pi呢?其实注意到const在int *const pi中的位置就大概能明白了。记住,通过格式看语义。哈哈,你可能看到图案了吧?没有必要阅读下面的部分。但我必须继续战斗。
再看int *const pi
的确,int *const pi很容易和之前的int const *pi混淆。注意:上一句的const写在pi之前,写在*之后,而不是*pi之前。很明显,是为了修改和限制圆周率。我先给你看一个例子:
#include 'stdio.h '
主()
{
/*代码开始*/
int i1=30
int i2=40
int * const pi=i1
/* pi=I2;注意pi不能这样重新分配,也就是不能指向另一个新地址。*/
/*所以我评论过了。*/
i1=80/*想想看:*这里可以用pi=80来代替?可以,这里可以通过*pi修改i1的值。(第5行的注释)*/
/*请将自己与前面的例子进行比较。*/
printf('%d ',* pi);/*输出为80 */
/*代码结束*/
}
语义分析:
看完这段代码你明白了什么?有没有发现pi值是不能重新分配和修改的?它只能永远指向初始化时的内存地址。相反,这次你可以通过*pi修改i1的值。和前面的例子比较一下。看下面两点分析:
因为pi是用const修饰的,所以它只是一个指针常量:也就是说,pi的值是不能修改的(即pi不能再指向i2)(请看第4行的注释)。
整个*pi前面没有const的修饰。也就是说,*pi是变量而不是常数,所以我们可以通过*pi修改它所引用的内存i1的值(请看第5行的注释)。
总之,这个pi是一个指针常量,指向int类型变量的数据。
我想用两句话来结束我的演讲:
如果在*pi之前修改了const,那么不能改变的就是*pi(也就是不能这样:* pi=50赋值)而不是引用pi。
如果const直接写在pi之前,pi是不能变的(也就是不能这样:pi=I;赋值)。
请先记住这两点,相信你不会再被它们迷惑了。现在看这两个语句,int const *pi和int *const pi,呵呵,会不会觉得头晕或者轻松?他们各自声明的pi能修改什么,不能修改什么?再想想这些问题。
补充三种情况
在这里,我想补充以下三种情况。其实只要把上面的语义说清楚,这三种情况就已经包含在内了。但作为三种具体形式,我还是简单提一下吧。
情况int * pi指针指向const int i constant的情况
#include 'stdio.h '
主()
{
/* begin */
const int i1=40
int * pi
pi=i1/*这样可以吗?不是,是VC下的编译错误。*/
/* consint类型的i1的地址不能赋给指向int类型地址的指针pi。否则pi不就可以修改i1的值了吗!*/
pi=(int *)i1;/*这样可以吗?C #可以支持类型转换.*/
/*在VC下编译,但是i1的值不能被*pi=80修改。试试看!我们来看看具体有多具体。*/
/* end */
}
第二种情况:const int *pi指针指向const int i1。
#include 'stdio.h '
主()
{
/* begin */
const int i1=40
const int * pi
pi=i1/*两者类型相同,可以这样赋值。显然,i1的值不能被pi或i1修改。*/
/* end */
}
案例3:用const int *const pi声明的指针
#include 'stdio.h '
主()
{
/* begin */
int I;
const int * const pi=I;/*你能想象pi能做什么吗?pi的值不能改变,I的值也不能被pi修改。因为*pi和pi都属于const。*/
/* end */
}
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。