此质料是摘要:<<彻底搞定C
指针 >>,自己感觉比较有价值,现与大家分享。

1. const int
说起

你知道我们声明一个变量时象这样int
i ;这个i是可能在它处重新变赋值的。如下:

int i = 0;

i = 20;

不过有一天我的程序可能需要这样一个变量(暂且称它变量),在声明时就赋一个初始值。之后我的程序在其它任何处都不会再去重新对它赋值。那我又应该怎么办呢?用const 。

const int ic =20;

ic = 40;

有了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 constic;一样。也就是说,它们是相同的。

好了,我们现在已经搞定一个“双包胎”的问题。那么

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;

i2 = 80;

printf("%d\n",*pi);

语义分析:

看出来了没有啊,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;

i1 = 80;

printf("%d",
*pi);

语义分析:

看了这段代码,你明白了什么?有没有发现pi值是不能重新赋值修改了。它只能永远指向初始化时的内存地址了。相反,这次你可以通过*pi来修改i1的值了。与前一个例子对照一下吧!看以下的两点分析:

1)pi因为有了const
的修饰,所以只是一个指针常量:也就是说pi值是不可修改的(即pi不可以重新指向i2这个变量了)(请看第4行的注释)。

2)整个*pi的前面没有const
的修饰。也就是说,*pi是变量而不是常量,所以我们可以通过*pi来修改它所指内存i1的值(请看第5行的注释)。

总之一句话,这次的pi是一个指向int变量类型数据的指针常量。

我最后总结两句:

1) 如果const
修饰在*pi前,则不能改的是*pi(即不能类似这样:*pi=50;赋值)而不是指pi。

2) 如果const
是直接写在pi前,则pi不能改(即不能类似这样:pi=&i;赋值)。

请你务必先记住这两点,相信你一定不会再被它们给搞糊了。现在再看这两个声明语句int const *pi和int
*constpi时,呵呵,你会头昏脑胀还是很轻松惬意?它们各自声明的pi分别能修改什么,不能修改什么?再问问

自己,把你的理解告诉我吧,可以发帖也可以发到我的邮箱(我的邮箱yyf977@163.com)!我一定会答复的。

4.补充三种情况

这里,我再补充以下三种情况。其实只要上面的语义搞清楚了,这三种情况也就已经被包含了。不过作为三种具体的形式,我还是简单提一下吧!

情况一:int
*pi指针指向const int i常量的情况

const int i1 =
40;

int *pi;

pi =
&i1;

pi = (int *)
&i1;

情况二:const int
*pi指针指向const int i1的情况

const int
i1=40;

const int *
pi;

pi=&i1;

情况三:用const int *const
pi声明的指针

int i;

const int *
constpi=&i;


0



const&nbsp;int&nbsp;*pi与int&amp;nbs…的更多相关文章

  1. VS2013 error C2556: “const int &Array<int>::operator [](int)”: 重载函数与“int &Array<int>::operator [](int)”只是在返回类型上不同

    1,VS2013 错误 1 error C2556: “const int &Array<int>::operator [](int)”: 重载函数与“int &Array ...

  2. (int &)a 和(int)a

      [cpp] view plain copy float a = 1.0f;     cout < < (int)a < < endl;     cout < < ...

  3. open_clientfd(char* hostname,int port)和open_listenfd(int port)

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h&g ...

  4. C语言复杂声明-void (*signal(int sig, void (*handler)(int)))(int);

    问题提出 请分析此声明:void (*signal(int sig, void (*handler)(int)))(int); 求解过程 在对上面的例子作分析之前,我们需要了解C语言的声明优先级,&l ...

  5. 编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试Stud

    package zuoye; public class student { int age; String name; int stuNO; void outPut() { System.out.pr ...

  6. C++中int *p[4]和 int (*q)[4]的区别

    这俩兄弟长得实在太像,以至于经常让人混淆.然而细心领会和甄别就会发现它们大有不同. 前者是指针数组,后者是指向数组的指针.更详细地说. 前: 指针数组;是一个元素全为指针的数组.后: 数组指针;可以直 ...

  7. 如何理解这段代码:void (*signal (int sinno,void(*func)(int)))(int)

    void (*signal (int sinno,void(*func)(int)))(int) 先来看void(*func)(int)   这里的意思是声明一个函数指针func,它的参数类型为int ...

  8. HSSFClientAnchor(int dx1,int dy1,int dx2,int dy2,short col1,int row1,short col2, int row2)

      public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int  ...

  9. C++中(int&)和(int)的区别

    在说这个问题之前,先说两个需要知道的背景知识: (1)语言的类型的强制转换不会修改原来的数据,会另外的开辟一个临时的或者程序中指定的空间来存储强制转换后的值. (2)C++引用的实现是在符号表中动了手 ...

随机推荐

  1. Oracle中的填充函数lpad和rpad的用法(转)

    原文链接:http://blog.csdn.net/myzhanglt/article/details/7392999 今日学习遇到一个不熟悉的函数LPAD,查了一下文档,将其用法总结如下: Lpad ...

  2. Week06《Java程序设计》第六次作业总结

    Week06<Java程序设计>第六次作业总结 1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行 ...

  3. MySQL 福利彩票业务 如何存储毫秒微秒

    朋友在做福利彩票业务,遇到一个存储毫秒微秒数据的需求,问我mysql里面有何解决方案.我脑中一搜索,以前没有关注到,于是去官网查看,找到11.3.6 Fractional Seconds in Tim ...

  4. Android 进阶10:进程通信之 Messenger 使用与解析

    读完本文你将了解: Messenger 简介 Messenger 的使用 服务端 客户端 运行效果 使用小结 总结 代码地址 Thanks 前面我们介绍了 AIDL 的使用与原理,这篇文章来介绍下 A ...

  5. hihocoder-1486物品价值(状压dp)

    题目链接: 物品价值 小Hi现在有n个物品,每个物品都有一个价值.并且这n个物品总共有m个不同的属性,每个物品都具有其中若干属性. 小Ho要从中选出若干物品,满足每个属性都正好有奇数个物品拥有,且被选 ...

  6. 【解题报告】2014ACM/ICPC上海赛区现场赛B

    唉  谷歌出的神题,差点爆零了...三小时终于A掉 B题 题目大概是说从左上角的点出发,经过某路线最后回到原点,求每个格子被路线包含的圈数的平方和. 首先可以知道,对于某个格子来说,从该格子的任意一个 ...

  7. fedora 安装新字体 courier new xxx

    fedora安装新字体 1.将windows字体拷贝到/usr/share/fonts/truetype下面,文件夹名字可以随便起 cp /media/c/WINDOWS/Fonts/* /usr/s ...

  8. fileUtil文件的上传下载

    package com.beisun.mbp.util; import java.io.BufferedInputStream;import java.io.BufferedOutputStream; ...

  9. win10 svn server安装过程中到starting service时失败

    当安装到Start Service阶段后,将会出错并会弹出一个对话框,提示是否要retry. (此时SVN服务软件已经安装完毕,仅仅是无法通过证书验证,无法启动服务),如果此时选择对话框中的cance ...

  10. Hadoop体系结构之 Mapreduce

    MR框架是由一个单独运行在主节点上的JobTracker和运行在每个集群从节点上的TaskTracker共同组成.主节点负责调度构成一个作业的所有任务,这些任务分布在不同的不同的从节点上.主节点监视它 ...