﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客--随笔分类-c</title><link>http://www.cppblog.com/dargon/category/18546.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 03 Feb 2012 17:39:09 GMT</lastBuildDate><pubDate>Fri, 03 Feb 2012 17:39:09 GMT</pubDate><ttl>60</ttl><item><title>指针常量，常指针，指向常量的常指针</title><link>http://www.cppblog.com/dargon/archive/2012/02/04/164918.html</link><dc:creator>玉香</dc:creator><author>玉香</author><pubDate>Fri, 03 Feb 2012 17:07:00 GMT</pubDate><guid>http://www.cppblog.com/dargon/archive/2012/02/04/164918.html</guid><wfw:comment>http://www.cppblog.com/dargon/comments/164918.html</wfw:comment><comments>http://www.cppblog.com/dargon/archive/2012/02/04/164918.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dargon/comments/commentRss/164918.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dargon/services/trackbacks/164918.html</trackback:ping><description><![CDATA[<div><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">1.常量指针（常指针）</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">int const*p</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">特点是指针指向的数值可以改变，然而指针所保存的地址却不可以改变</span>。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">2.指针常量</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">const int*p</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">特点是指针所保存的地址可以改变，然而指针所指向的值却不可以改变</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">3.指向常量的常指针</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">const int const*p</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">特点是指针所保存的地址不可变，指针所指向的数值也不可变</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">4.空指针</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">顾名思义，就是保存地址为空的指针</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">int *p=0;&nbsp;&nbsp; //此时的指针p就是一个空指针</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">5.内存泄露</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">int *p=new int;</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">p=new int;</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">delete p;&nbsp;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//用delete来释放刚刚申请的那块内存区域，注意此时指针p还是可能依旧指向的这块区域(注意可能二字)。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">这样就会有内存丢失，也就是所谓的内存泄漏。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #339966; ">因为第一行我们在堆中申请了一块int型的区域，并且用指针p指向该空间。但是紧接着我们又在堆中申请了一块int型的区域，用p指向了该空间。</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #339966; ">那么先前申请的那块区域就无法访问了，但同时这块无法访问的区域没有被删除。所以就造成了内存泄漏。</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">6.迷途指针</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">int *p=new int;&nbsp;&nbsp; //在堆中申请一块区域，用p指向这块区域</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-color: #ffff00; ">所以此时指针p的指向地址具有不确定性，故而称作迷途指针，避免的方法是将指针初始化为空指针。</span></p></div><img src ="http://www.cppblog.com/dargon/aggbug/164918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dargon/" target="_blank">玉香</a> 2012-02-04 01:07 <a href="http://www.cppblog.com/dargon/archive/2012/02/04/164918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常量指针和指针常量</title><link>http://www.cppblog.com/dargon/archive/2012/02/04/164917.html</link><dc:creator>玉香</dc:creator><author>玉香</author><pubDate>Fri, 03 Feb 2012 17:05:00 GMT</pubDate><guid>http://www.cppblog.com/dargon/archive/2012/02/04/164917.html</guid><wfw:comment>http://www.cppblog.com/dargon/comments/164917.html</wfw:comment><comments>http://www.cppblog.com/dargon/archive/2012/02/04/164917.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dargon/comments/commentRss/164917.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dargon/services/trackbacks/164917.html</trackback:ping><description><![CDATA[<div><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>一、可能的组合：</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (1)const char*p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; (2)char const*p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (3)char *const p<br />&nbsp; &nbsp;&nbsp; (4)const char **p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (5)char const**p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (6)char *const *p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (7)char **const p</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 当然还有在(5)、(6)、(7)中再插入一个const的若干情况，不过分析了以上7中，其他的就可类推了！</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>二、理解助记法宝：</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;&nbsp;<strong><span style="color: #ff0000; ">1。关键看const 修饰谁。</span></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;&nbsp;<span style="color: #ff0000; "><strong>2。由于没有const *的运算，若出现const*的形式，则const实际上是修饰前面的。</strong></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 比如：char const*p,由于没有const*运算，则const实际上是修饰前面的char，因此char const*p等价于const char*p。也就是说上面7种情况中，（1）和（2）等价。 同理，（4）和（5）等价。在（6）中，由于没有const*运算，const实际上修饰的是前面的char*,但不能在定义时转换写成 const(char *)*p，因为在定义是"()"是表示函数。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>三、深入理解7种组合</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>&nbsp; &nbsp;&nbsp; (0)程序</strong>&nbsp;<strong>在执行时为其开辟的空间皆在内存（RAM）中，而RAM里的内存单元是<span style="color: #ff0000; ">可读可写</span>&nbsp;的；<span style="color: #ff0000; ">指针只是用来指定或定位要操作的数据的工具，只是用来读写RAM里内存单元的工作指针</span>&nbsp;。若对指针不加任何限定，程序中一个指针可以指向RAM中的任意位置（除了系统敏感区，如操作系统内核所在区域）并对其指向的内存单元进行读和写操作（由RAM的可读可写属性决定）；RAM里内存单元的可读可写属性不会因为对工作指针的限定而变化（见下面的第4点），而<span style="color: #ff0000; ">所有对指针的各种const限定说白了只是对该<span style="color: #0000ff; ">指针</span>&nbsp;的</span>&nbsp;<span style="color: #ff0000; "><span style="color: #0000ff; ">读写权限</span>&nbsp;（包括读写位置）进行了限定</span>&nbsp;。<br /></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (1)char *p：p是一个工作指针，可以用来对<strong><span style="color: #ff0000; ">任意位置</span>&nbsp;</strong>（非系统敏感区域）进 行<strong><span style="color: #ff0000; ">读操作和写操作</span>&nbsp;</strong>，一次读写一个字节（char占一个字节）。<br />&nbsp;&nbsp;&nbsp;&nbsp; (2)const char*p或者char const *p（因为没有const*p运算，因此const修饰的还是前面的char）：可以对任意位置（非系统敏感区域）进行<strong><span style="color: #ff0000; ">&#8220;只读&#8221;</span>&nbsp;</strong>操作。（&#8220;只读&#8221;是相对于char *p来说所限定的内容）<br />&nbsp; &nbsp;&nbsp; (3)char *const p（const 修饰的是p）：只能对<strong><span style="color: #ff0000; ">&#8220;某个固定的位置&#8221;</span>&nbsp;</strong>进 行读写操作，并且在定义p时就必须初始化（因为在后面不能执行&#8220;p=..&#8221;的操作，因此就不能在后面初始化，因此只能在定义时初始化）。（&#8220;某个固定的位 置&#8221;是相对于char *p来说所限定的内容）<br />可以总结以上3点为：char *p中的指针p通常是<strong><span style="color: #ff0000; ">&#8221;万能&#8221;的工作指针</span>&nbsp;</strong>，而（2）和（3）只是在（1）的基础上<strong><span style="color: #ff0000; ">加了些特定的限制</span>&nbsp;</strong>，这些限制在程序中并不是必须的，只是为了防止程序员的粗心大意而产生事与愿违的错 误。<br />另外，要明白<strong>&#8220;<span style="color: #ff0000; ">每块内存空间都可有名字；每块内存空间内容皆可变（除非有所限）</span>&nbsp;&#8221;</strong>&nbsp;。比如函数里定义的char s[]="hello";事实上在进程的栈内存里开辟了6个变量共6个字节的空间，其中6个字符变量的名字分别为：s1[0]、s1[1]、 s1[2]、s1[3]、s1[4]、s1[5]（内容是'/0'）</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong><span style="color: #ff0000; ">{</span></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;<span style="font-family: mceinline; "><strong>待验证</strong>&nbsp;(见后面问题3的分析)</span>&nbsp;：&nbsp;<strong><span style="color: #ff0000; ">还有一个4字节的指针变量s</span>&nbsp;</strong>。不过s是&#8220;有所限制&#8221;的，属于char *const类型，也就是前面说的&nbsp;&nbsp; (3)这种情况,s一直指向s［0］, &nbsp; &nbsp;即（*s==s[0]=='h'）,可以通过*s='k'来改变s所指向的 s[0]的值，但不能执行（char *h＝&#8220;aaa&#8221;;s=h;）来对s另外赋值。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong><span style="color: #ff0000; ">}</span></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; (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＝&#8216;A&#8217;,c是RAM里一个内存单元（8字节）的名字，该内存单元的内容只可读，不可写。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp; (5)const char **p或者char const**p ：涉及两个指针p和 *p。由于const修饰char ，对指针p没有任何限定，对指针*p进行了上面情况(2)的限定。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; (6)char *const *p：涉及两个指针p和 *p。由于const修饰前面的char*,也就是对p所指向的内容*p进行了限定(也属于前面的情况(2))。而对*p来说，由于不能通过"*p＝..."来进行另外赋值，因此属于前面的情况(3)的限定。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; (7)char **const p ： 涉及两个指针p和 *p，const修饰p，对p进行上面情况(3)的限定，而对*p,没有任何限定。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>四、关于char **p 、const char **p的类型相容性问题</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;<strong>1。问题</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *p1;const *p2=p1;//合法</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char **p1;const&nbsp; char**p2=p1;//不合法，会有警告warning: initialization from incompatible pointer type</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char **p1;char const**p2=p1;//不合法，会有警告warning: initialization from incompatible pointer type</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char**p1;char*const*p2=p1;//合法</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;<strong>&nbsp;2。判断规则</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 明确const修饰的对象！对于指针p1，和p2，<strong><span style="color: #ff0000; ">若要使得p2=p1成立，则可读做</span>&nbsp;</strong>：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000; "><strong>&#8220;p1是指向X类型的指针，p2是指向&#8220;带有const限定&#8221;的X类型的指针</strong>&nbsp;</span><strong><span style="color: #ff0000; ">&#8220;。</span></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; char *p1;const *p2=p1;//合法:p1是指向（char）类型的指针，p2是指向&#8220;带有const限定"的(char)类型的指针。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char **p1;const&nbsp; char**p2=p1;//不合法:p1是指向（char*）类型的指针,p2是指向 ((const char)*)类型的指针。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; char **p1;char const**p2=p1;//不合法;与上等价。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; char**p1;char*const*p2=p1;//合法:&nbsp; p1是指向（char *）类型的指针，p2是指向&#8220;带有const限定"的(char*)类型的指针。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>五、其他</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; 1。 含有const的单层或双层指针的统一读法：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000; "><strong>&#8220;p是一个指针，是一个［&#8220;带有const限定&#8221;的］指向［&#8221;带有const限定&#8221;的］X类型的指针&#8221;。</strong></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; 2。定义时const修饰的对象是确定的，但不能在定义时加括号，不然就和定义时用&#8220;（）&#8221;表示的函数类型相混淆了！因此定义时不能写(char *)const *p或者(const char) **p。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>六、问题探讨（由于博文后的留言有字符数目限制，将回复移到这里）</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;<span style="color: #ff0000; "><strong>问题1</strong>&nbsp;</span>（见博文后留言）：<span style="color: #ff00ff; "><span style="border-collapse: separate; font-family: 'Times New Roman'; line-height: normal; font-size: medium; "><span style="font-family: verdana, sans-serif; font-size: 12px; line-height: 18px; ">讲解非常好，不过有个问题想探讨下： 例如： const char wang[]={"wang"}; char *p; p=wang; 是错误的。 所以char *p中的P不能指向常变量。 （1）需要补充纠正。</span></span></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #ff0000; ">&nbsp;&nbsp;<strong>回复</strong>&nbsp;：</span>&nbsp;<span style="color: #0000ff; ">你好！谢谢指正！我在ubuntu 10.04（gcc 4.4.3）下做了如下测试：</span>&nbsp;<br />&nbsp;&nbsp; //test_const.c<br />&nbsp;&nbsp; #include&lt;stdio.h&gt;<br />&nbsp;&nbsp; int main()<br />&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp; const char wang[]={"wang"};<br />&nbsp;&nbsp;&nbsp;&nbsp; char *p;<br />&nbsp;&nbsp;&nbsp;&nbsp; p=wang;<br />&nbsp;&nbsp;&nbsp;&nbsp; p[2]='c';<br />&nbsp;&nbsp;&nbsp;&nbsp; printf("p is %s/n",p);<br />&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />&nbsp; }<br /><strong>编译</strong>&nbsp;：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gcc -o test_const test_const.c<br /><strong>输出如下</strong>&nbsp;：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test_const.c: In function &#8216;main&#8217;:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test_const.c:17: warning: assignment discards qualifiers from pointer target type<br /><strong>执行：</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./test_const<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p is wacg<br /><strong>结论：</strong>&nbsp;<span style="color: #0000ff; ">根据本博文中第四点－－相容性问题，将const型的wang赋值给p是不合法的。但编译器对其的处理只是警告，因此执行时通过p修改了只读区域的数据。这应该是该编译器处理不严所致后果，不知你用的什么编译器？</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; "><span style="color: #ff0000; "><strong>&nbsp;&nbsp;&nbsp; 问题2&nbsp;&nbsp;</strong><span style="color: #ff00ff; ">回答&nbsp;</span></span></span><span style="color: #ff00ff; "><a href="http://www.linuxsir.org/bbs/showthread.php?t=239058" style="color: #ca0000; text-decoration: none; ">http://www.linuxsir.org/bbs/showthread.php?t=239058</a>&nbsp;</span><span style="color: #0000ff; "><span style="color: #ff00ff; ">提到的问题</span></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #ff00ff; ">在c语言里</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #ff00ff; ">// test.c<br />int main() {<br />&nbsp;&nbsp; const char* s1 = "test";<br />&nbsp;&nbsp; char *s2 = s1;<br />&nbsp;&nbsp; s2 = "It's modified!";<br />&nbsp;&nbsp; printf("%s/n",s1);<br />}<br />out: It's modified!;<br />这样也可以吗? 照我的理解岂不是const限定符在c语言里只是摆设一个？</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #ff0000; "><strong>&nbsp;&nbsp;&nbsp;&nbsp; 回复：</strong></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong></strong><span style="color: #0000ff; ">(1)首先，以上代码编译时会出错warning: initialization discards qualifiers from pointer target type，</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">&nbsp;&nbsp;&nbsp;&nbsp; 因为char *s2 = s1和问题1提到的一样，不符合相容规则。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; "><br /></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">(2)输出结果是正确的，代码分析如下：</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;<span style="color: #ff00ff; ">int main() {<br />&nbsp;&nbsp; const char* s1 = "test";&nbsp;&nbsp;<span style="color: #0000ff; ">//&nbsp; 在只读数据区（objdump -h test后的.rodata区）开辟5字节存储"test",并用s1指向首字符&#8216;t&#8217;。</span>&nbsp;<br />&nbsp;&nbsp; char *s2 = s1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">//&nbsp; s2也指向只读数据区中&#8220;test&#8221;的首字符't'。</span>&nbsp;<br />&nbsp;&nbsp; s2 = "It's modified!";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">&nbsp;//</span>&nbsp;</span><span style="color: #0000ff; ">在只读数据区开辟15字节存储"It's modified!"，并将s2由指向't'转而指向"It's modified!"的首字符'I'。</span>&nbsp;<br /><span style="color: #ff00ff; ">&nbsp;&nbsp; printf("%s/n",s1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">// 从s1所指的&#8216;t&#8217;开始输出字符串"test"。</span>&nbsp;<br />}</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; "><br />(3)总结：提问者的误区在于，误以为s2 = "It's modified!"是对&#8220;test&#8221;所在区域的重新赋值，其实这里只是将&#8220;万能&#8221;工作指针s2指向另外一个新开辟的区域而已。比如若在char *s2 = s1后再执行s2[2]='a'则是对&#8220;test&#8221;的区域进行了写操作，执行时会出现段错误。但这个段错误其实与const没有关系，因为&#8220;test&#8221;这块区域本身就是只读的。为了防止理解出错，凡事对于对指针的赋值（比如</span>&nbsp;<span style="color: #ff00ff; ">s2 = "It's modified!"</span>&nbsp;<span style="color: #0000ff; ">），则将其读做：将s2指向&#8220;</span>&nbsp;<span style="color: #ff00ff; ">It's modified!</span>&nbsp;<span style="color: #0000ff; ">&#8221;所在区域的首字符。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; "><br /></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">(4)额外收获：执行gcc -o test test.c后，&#8220;test&#8221;、&#8220;It's modified!&#8221;、"%s/n"都被作为字符串常量存储在二进制文件test的只读区</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">&nbsp;&nbsp;&nbsp; 域 (.rodata)。事实上，一个程序从编译到运行，对变量空间分配的情况如下：</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">A。赋值了的全局变量或static变量=&gt;放在可执行文件的.data段。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">B。未赋值的全局变量或static变量＝&gt;放在可执行文件的.bss段。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">C。代码中出现的字符串常量或加了const的A＝&gt;放在可执行文件的.rodata段。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">D。一般的局部变量＝&gt;在可执行文件中不占空间，在该二进制文件作为进程在内存中运行时才为它分配栈空间。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">E。代码中malloc或new出的变量＝&gt;在可执行文件中不占空间，在该二进制文件作为进程在内存中运行时才为它分配堆空间。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">&nbsp;&nbsp;&nbsp;<span style="color: #ff0000; "><strong>&nbsp;问题3：（待进一步分析）</strong>&nbsp;</span>验证博文中 三（3）提到的是否为s分配空间，初步分析结果为：不分配！文中的s只是s［0］的地址的代号而已。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">#include&lt;stdio.h&gt;<br />int main() {<br />&nbsp;&nbsp;&nbsp; int a=3;<br />&nbsp;&nbsp;&nbsp; char s1[] = "test";<br />&nbsp;&nbsp;&nbsp; int b=4;<br />&nbsp;&nbsp;&nbsp; char s2[] ="test2";<br />&nbsp;&nbsp;&nbsp; printf("the address of a is %u/n",&amp;a);<br />&nbsp;&nbsp;&nbsp; printf("s1 is %u/n",s1);<br />&nbsp;&nbsp;&nbsp; printf("the address of s1 is %u/n",&amp;s1);<br />&nbsp;&nbsp;&nbsp; printf("the address of b is %u/n",&amp;b);<br />&nbsp;&nbsp;&nbsp; printf("s2 is %u/n",s2);<br />&nbsp;&nbsp;&nbsp; printf("the address of s2 is %u/n",&amp;s2);<br />&nbsp;&nbsp; }</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #0000ff; ">输出结果：<br /></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="color: #ff00ff; ">the address of a is 3213037836<br />s1 is 3213037827<br />the address of s1 is 3213037827<br />the address of b is 3213037832<br />s2 is 3213037821<br />the address of s2 is 3213037821<br /></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">由结果可以看出，编译器做了些优化。</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>&nbsp;七、其他相关经典文章转载</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong></strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;<strong>王海宁,</strong>&nbsp;<a href="http://www.embedu.org/" target="_blank" style="color: #ca0000; text-decoration: none; ">华清远见嵌入式学院</a>&nbsp;<span style="color: #666666; ">讲师，<strong>对const关键字的理解</strong></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;<a href="http://www.embedu.org/Column/Column311.htm" style="color: #ca0000; text-decoration: none; ">http://www.embedu.org/Column/Column311.htm</a></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 目前在进行C语言补习时，发现很多的同学对于const这个关键字的理解存在很大的误解。现在总结下对这个关键字理解上的误区，希望在以后的编程中，能够灵活使用const这个关键字。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>1、 const修饰的变量是常量还是变量</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 对于这个问题，很多同学认为const修饰的变量是不能改变，结果就误认为该变量变成了常量。那么对于const修饰的变量该如何理解那？</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">下面我们来看一个例子：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">int main<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char buf[4];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const int a = 0;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a = 10;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 这个比较容易理解，编译器直接报错，原因在于&#8220;a = 10；&#8221;这句话，对const修饰的变量，后面进行赋值操作。这好像说明了const修饰的变量是不能被修改的，那究竟是不是那，那么下面我们把这个例子修改下：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">int main<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char buf[4];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const int a = 0;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[4] = 97;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&#8220;the a is %d/n&#8221;,a);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">其中最后一句printf的目的是看下变量a的值是否改变，根据const的理解，如果const修饰的是变量是不能被修改的话，那么a的值一定不会改变，肯定还是0。但是在实际运行的结果中，我们发现a的值已经变为97了。这说明const修饰的变量a，已经被我们程序修改了。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">那综合这两个例子，我们来分析下，对于第二例子，修改的原因是buf[4]的赋值操作，我们知道buf[4]这个变量已经造成了buf这个数组变量的越界访问。buf数组的成员本身只有0,1,2,3，那么buf[4]访问的是谁那，根据局部变量的地址分配，可以知道buf[4]的地址和int a的地址是一样，那么buf[4]实际上就是访问了const int a；那么对buf[4]的修改，自然也修改了const int a的空间，这也是为什么我们在最后打印a的值的时候看到了97这个结果。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">那么我们现在可以知道了，const修饰的变量是不具备不允许修改的特性的，那么对于第一个例子的现象我们又如何解释那。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">第一个例子，错误是在程序编译的时候给出的，注意这里，这个时候并没有生成可执行文件，说明const修饰的变量可否修改是由编译器来帮我们保护了。而第二个例子里，变量的修改是在可执行程序执行的时候修改的，说明a还是一个变量。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">综上所述，我们可以得出一个结论，那就是const修饰的变量，其实质是告诉程序员或编译器该变量为只读，如果程序员在程序中显示的修改一个只读变量，编译器会毫不留情的给出一个error。而对于由于像数组溢出，隐式修改等程序不规范书写造成的运行过程中的修改，编译器是无能为力的，也说明const修饰的变量仍然是具备变量属性的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><strong>2、 被const修饰的变量，会被操作系统保护，防止修改</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果对于第一个问题，有了理解的话，那么这个问题，就非常容易知道答案了。Const修饰的变量是不会被操作系统保护的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">其原因是操作系统只保护常量，而不会保护变量的读写。那么什么是常量？比如&#8220;hello world&#8221;这个字符串就是被称为字符串常量。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">对于这个问题的另一种证明方法，可以看下面这个程序：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">int main ()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const int a;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char *buf = "hello world";</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("the &amp;a is %p, the buf is %p/n",&amp;a, buf);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">可以发现buf保存的地址是在0x08048000这个地址附近的，而a的地址是在0xbf000000这个地址附近的，而0x08048000附近的地址在我们linux操作系统上是代码段。这也说明了常量和变量是存放在不同区域的，自然操作系统是会保护常量的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">如果我们知道这个道理后，再看下面的题目：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">#include&lt;stdio.h&gt;<br />int main()<br />{<br />&nbsp;char *buf = "hello";<br />&nbsp;buf[0] = 'a';<br />&nbsp;printf("the buf is %s/n",buf);<br />}</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">我们可以思考下，这个程序的运行结果会是什么呢？</p></div><img src ="http://www.cppblog.com/dargon/aggbug/164917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dargon/" target="_blank">玉香</a> 2012-02-04 01:05 <a href="http://www.cppblog.com/dargon/archive/2012/02/04/164917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>