一、可能的组合:

(1)const char*p

(2)char const*p

(3)char *const p
(4)const char **p

(5)char const**p

(6)char *const *p

(7)char **const p

当然还有在(5)、(6)、(7)中再插入一个const的若干情况,不过分析了以上7中,其他的就可类推了!

二、理解助记法宝:

1、关键看const 修饰谁。

2、由于没有 const *的运算,若出现 const * 的形式,则const实际上是修饰前面的。

比如:char const*p,由于没有const*运算,则const实际上是修饰前面的char,因此char const*p等价于const char*p。也就是说上面7种情况中,(1)和(2)等价。 同理,(4)和(5)等价。在(6)中,由于没有const*运算,const实际上修饰的是前面的char*,但不能在定义时转换写成 const(char *)*p,因为在定义是"()"是表示函数。

三、深入理解7种组合

  程序 在执行时为其开辟的空间皆在内存(RAM)中,而RAM里的内存单元是可读可写 的;指针只是用来指定或定位要操作的数据的工具,只是用来读写RAM里内存单元的工作指针 。若对指针不加任何限定,程序中一个指针可以指向RAM中的任意位置(除了系统敏感区,如操作系统内核所在区域)并对其指向的内存单元进行读和写操作(由RAM的可读可写属性决定);RAM里内存单元的可读可写属性不会因为对工作指针的限定而变化(见下面的第4点),而所有对指针的各种const限定说白了只是对该指针 的 读写权限 (包括读写位置)进行了限定 。

(1)char *p:p是一个工作指针,可以用来对任意位置 (非系统敏感区域)进 行读操作和写操作 ,一次读写一个字节(char占一个字节)。

  注: 特例: const char wang[]={"wang"}; char *p; p=wang; 是错误的。 所以char *p中的P不能指向常变量
(2)const char*p或者char const *p(因为没有const*p运算,因此const修饰的还是前面的char):可以对任意位置(非系统敏感区域)进行“只读” 操作。(“只读”是相对于char *p来说所限定的内容)

(3)char *const p(const 修饰的是p):只能对“某个固定的位置” 进 行读写操作,并且在定义p时就必须初始化(因为在后面不能执行“p=..”的操作,因此就不能在后面初始化,因此只能在定义时初始化)。(“某个固定的位 置”是相对于char *p来说所限定的内容)

可以总结以上3点为:char *p中的指针p通常是”万能”的工作指针 ,而(2)和(3)只是在(1)的基础上加了些特定的限制 ,这些限制在程序中并不是必须的,只是为了防止程序员的粗心大意而产生事与愿违的错 误。
另外,要明白“每块内存空间都可有名字;每块内存空间内容皆可变(除非有所限) ” 。比如函数里定义的char s[]="hello";事实上在进程的栈内存里开辟了6个变量共6个字节的空间,其中6个字符变量的名字分别为:s1[0]、s1[1]、 s1[2]、s1[3]、s1[4]、s1[5](内容是'\0')

{

待验证 : 还有一个4字节的指针变量s 。不过s是“有所限制”的,属于char *const类型,也就是前面说的 (3)这种情况,s一直指向s[0], 即(*s==s[0]=='h'),可以通过*s='k'来改变s所指向的 s[0]的值,但不能执行(char *h=“aaa”;s=h;)来对s另外赋值。

}

(4)上面的(2)和(3)只是对p进行限定,没有也不能对p所指向的空间进行限定,对于"char s[]="hello";const char*p=s;" 虽然不能通过*(p+i)='x'或者p[i]='x'来修改数组元素s[0]~s[4]的值,但可以通过*(s+i)='x'或者s[i]='x'来修改原数组元素的值--RAM里内存单元的可读可写属性不因对工作指针的限定而改变,而只会因对其本身的限定而改变。如const char c=‘A’,c是RAM里一个内存单元(8字节)的名字,该内存单元的内容只可读,不可写。

(5)const char **p或者char const**p :涉及两个指针p和 *p。由于const修饰char ,对指针p没有任何限定,对指针*p进行了上面情况(2)的限定。

(6)char *const *p:涉及两个指针p和 *p。由于const修饰前面的char*,也就是对p所指向的内容*p进行了限定(也属于前面的情况(2))。而对*p来说,由于不能通过"*p=..."来进行另外赋值,因此属于前面的情况(3)的限定。

(7)char **const p : 涉及两个指针p和 *p,const修饰p,对p进行上面情况(3)的限定,而对*p,没有任何限定。

四、关于char **p 、const char **p的类型相容性问题

1、问题

char *p1;const *p2=p1;//合法

char **p1;const char**p2=p1;//不合法,会有警告warning: initialization from incompatible pointer type

char **p1;char const**p2=p1;//不合法,会有警告warning: initialization from incompatible pointer type

char**p1;char*const*p2=p1;//合法

2、判断规则

明确const修饰的对象!对于指针p1,和p2,若要使得p2=p1成立,则可读做 :

“p1是指向X类型的指针,p2是指向“带有const限定”的X类型的指针 “。只要二者的X类型一样,就是合法的。

char *p1;const *p2=p1;//合法:p1是指向(char)类型的指针,p2是指向“带有const限定"的(char)类型的指针。

char **p1;const char**p2=p1;//不合法:p1是指向(char*)类型的指针,p2是指向 ((const char)*)类型的指针。

char **p1;char const**p2=p1;//不合法;与上等价。

char**p1;char*const*p2=p1;//合法: p1是指向(char *)类型的指针,p2是指向“带有const限定"的(char*)类型的指针。

五、其他

1、含有const的单层或双层指针的统一读法:

“p是一个指针,是一个[“带有const限定”的]指向[”带有const限定”的]X类型的指针”。

l例如:const char* const *p就是说:p是一个带有const限定的指向带有const限定的(char*)类型的指针。

2、定义时const修饰的对象是确定的,但不能在定义时加括号,不然就和定义时用“()”表示的函数类型相混淆了!因此定义时不能写(char *)const *p或者(const char) **p。

【转】深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p的更多相关文章

  1. 深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p

    由于没有const*运算,const实际上修饰的是前面的char*,但不能在定义时转换写成 const(char *)*p,因为在定义是"()"是表示函数. 三.深入理解7种组合 ...

  2. C++形参中const char * 与 char * 的区别

    在函数调用时,我们经常看见一个函数的接受参数为(const char *); 例如strlen()函数,它的定义为: size_t strlen( const char *str); 那么将形参设置为 ...

  3. C++编译遇到参数错误(cannot convert parameter * from 'const char [**]' to 'LPCWSTR')

    转:http://blog.sina.com.cn/s/blog_9ffcd5dc01014nw9.html 前面的几天一直都在复习着被实习落下的C++基础知识.今天在复习着上次创建的窗口程序时,出现 ...

  4. const char *p; char const *p; char * const p的区别

    请看下面三种定义: const char *p; char const *p; char * const p; 首先看第一种,我们先看p,本着”从里往外”的原则,p是一个char *类型的变量,但ch ...

  5. C++ 字符串、string、char *、char[]、const char*的转换和区别

    1.字符串 字符串本质就是一串字符,在C++中大家想到字符串往往第一反应是std::string(后面简称string) 字符串得从C语言说起,string其实是个类,C语言是没有class的,所以C ...

  6. 【C/C++】字符数组:char,char*,char a[], char *a[], char **s 的区别与联系/const char*和char*的区别

    一.char,char*,char a[], char *a[], char **s 的区别与联系 C语言中的字符串是字符数组,可以像处理普通数组一样处理字符串. 可以理解为在内存中连续存储的字符. ...

  7. const char*、char*、char* const、char[]、string的区别

    1.const char* p: p is a pointer to const char(char const* p 一样)   意思就是不能通过p指针来修改p指向的内容(但是内容可以修改). 2. ...

  8. const char *p;和char * const p的区别

    const char *p;       const修饰*p,所以*p是一个常量,不可修改. char* const p; const修饰p,所以指针p是一个常量,不可修改. #include< ...

  9. char *与const char **函数参数传参问题

    传参方法 ## 函数 extern void f2 ( const char ** ccc ); const char ch = 'X'; char * ch_ptr; const char ** c ...

随机推荐

  1. Mac Pro 安装 最新版的 SVN 1.9.4

    系统自带的 SVN 版本为 1.7.2 $ svn --version svn, version 1.7.22 (r1694152) 有点老,安装下最新版本 brew install svn 由于老版 ...

  2. appid 评价

    //apple api #define kAppAppleId         @"980883989" #define kAppRateUrl         @"it ...

  3. ORACLE 数据库建了非法表后无法操作和删除问题

    问题描述: oracle 用PL/SQL DEVELOPER 可视化建表时,表名没有按照规范,建立一个非法格式的表 ICD-10th-Version (中间有横杆,非法).但是不知道怎么回事却建成功了 ...

  4. 利用LruCache为GridView加载大量本地图片完整示例

    MainActivity如下: package cc.testlrucache; import android.os.Bundle; import android.widget.GridView; i ...

  5. 使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments

    使用C++扩展Python的功能 环境 VS2005Python2.5.4 Windows7(32位) 简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python ...

  6. Linux的五个查找命令

    1. find find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件. find的使用格式如下: $ find <指定目录> <指定条件> <指定动作> ...

  7. STM32F103ZET6 用定时器级联方式输出特定数目的PWM(转载)

    STM32F103ZET6里共有8个定时器,其中高级定时器有TIM1-TIM5.TIM8,共6个.这里需要使用定时器的级联功能,ST的RM0008 REV12的P388和P399页上有说明对于特定的定 ...

  8. centos: vmware 安装centos 7连不上网

    在vmware上安装centos 7时,安装完成后无法连接网络,通过搜索查找原来是有线网卡没有激活,默认情况下centos和redhat都不启用有线网卡,只能手动开启或者安装时直接启用. 1.进入命令 ...

  9. Graphic32中TBitmap32.TextOut性能分析[转载]

    转载:http://blog.csdn.net/avan_lau/article/details/6958497 最近在分析软件中画线效率问题,发现在画一些标志性符号的方法,存在瓶颈,占用较大的时间. ...

  10. 【云计算】docker前世今生

    下一代云计算模式:Docker正掀起个性化商业革命 作者: 吴宁川  来源: ITValue  发布时间: 2015-09-20 10:41  阅读: 12976 次  推荐: 24          ...