﻿<?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++博客-X-LIN-随笔分类-C++</title><link>http://www.cppblog.com/X-LIN/category/20138.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 25 Oct 2012 11:10:10 GMT</lastBuildDate><pubDate>Thu, 25 Oct 2012 11:10:10 GMT</pubDate><ttl>60</ttl><item><title>char str[] 和 char *str 的区别</title><link>http://www.cppblog.com/X-LIN/archive/2012/10/25/193850.html</link><dc:creator>林</dc:creator><author>林</author><pubDate>Thu, 25 Oct 2012 10:40:00 GMT</pubDate><guid>http://www.cppblog.com/X-LIN/archive/2012/10/25/193850.html</guid><wfw:comment>http://www.cppblog.com/X-LIN/comments/193850.html</wfw:comment><comments>http://www.cppblog.com/X-LIN/archive/2012/10/25/193850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/X-LIN/comments/commentRss/193850.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/X-LIN/services/trackbacks/193850.html</trackback:ping><description><![CDATA[<div class="postbody">
<div id="cnblogs_post_body">
<p>char*&nbsp;get_str(void)&nbsp;&nbsp;<br />{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;str[]&nbsp;=&nbsp;{"abcd"};&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str;&nbsp;&nbsp;<br />}&nbsp; </p>
<p style="text-indent: 2em"><span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong style="text-indent: 2em"><font size="2">char str[] = {"abcd"};定义了一个局部字符数组</font></strong></span>，尽管是数组，但它是一个局部变量，返回它的地址肯定是一个已经释放了的空间的地址。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此函数返回的是内部一个局部字符数组str的地址，且<span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong><font size="2">函数调用完毕后 此数组被销毁</font></strong></span>，所以你返回的指针也就指向一块被销毁的内存，这种写法是错误的。</p>
<p><br />char*&nbsp;get_str(void)&nbsp;&nbsp;<br />{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*str&nbsp;=&nbsp;{"abcd"};&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str;&nbsp;&nbsp;<br />}&nbsp; </p>
<p style="text-indent: 2em"><span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong style="text-indent: 2em"><font size="2">char* str = {"abcd"};表示先定义个字符串常量，并将其地址赋给str。<br /></font></strong></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此函数返回的是字符串常量的地址，而像这种字符串都是属于全局的，在编译的时候就已经分配了内存了，只有程序退出的时候才会被销毁，所以返回它的地址是没有问题的，但是你最好返回常量指针，因为你不能去改变字符串常量的值。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 这个str就在栈里面，但后面的字符串在常量区，函数返回的时候，先将常量区的地址返回，然后作用域结束，释放str在栈里面的空间。。<br />const&nbsp;char&nbsp;str[]&nbsp;=&nbsp;"abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//abc存储在堆栈中 &nbsp;&nbsp;<br />const&nbsp;char&nbsp;*str&nbsp;=&nbsp;"abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//abc存储在静态存储区&nbsp; </p>
<p style="text-indent: 2em">准确的说，上面两个&#8220;abc"都是存储在静态存储区，即常量区。常量区是可读不可写的。所以任何试图对常量区进行写的操作都是非法的，当然了，这也不是一 定不可写的，你可以采取某种渠道改变常量区的内存属性，比如改变pe相关节的属性就可以对常量区进行读写，当然了，这个目前可以忽略。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong><font size="2"> 那么为什么str[] = "abc";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以写呢？&nbsp;&nbsp; 答案就在str[] = "abc"；会有一个额外的拷贝过程，即把常量区的 "abc"拷贝到栈内存去，所以就可以写了。</font></strong></span></p>
<p><font size="2"></font></p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总结：<br /><span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong><font size="2">所有以" "或' '包含的字符、字符串都是常量，应该是存储在堆上。<br /></font></strong></span>char *str = "xxxxx"，str指向该常量地址。<br />char str[] = "xxxxx"，str在栈上申请空间，将常量内容复制进来，所以是局部变量。</p>
<p>&nbsp;</p>
<p style="text-indent: 2em">首先，数组和指针是不同的数据类型，有本质的区别：<br />char str[] = "abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //sizeof(str) == 5 * sizeof(char)<br />char * str = "abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //sizeof(str) == 4(x86) or 8(x64)<br />数组可以自动转型成指针，指针不能转成数组。</p>
<p>&nbsp;</p>
<p style="text-indent: 2em">然后，字符串等价于字符数组，而不等于字符指针。根据上一条，字符串可以自动转型成字符指针。</p>
<p>&nbsp;</p>
<p style="text-indent: 2em">再然后，"abcd"叫做&#8220;字符串常量&#8221;，任何类型的常量都是右值（没有名字的临时变量），必须让"abcd"成为左值（有名字的变量），才能够修改"abcd"这个字符串。<br />char str[] = "abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;//等号两端是相同的数据类型，右值成为左值<br /><span style="color: #ff0000" color="#ff0000"><strong>char * str = "abcd";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //等号两端是不同的数据类型，右端自动转型成char*，该char*得到了str的名字，而"abcd"这个char数组仍然没有名字。</strong></span></p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><span style="color: #ff0000; font-size: small" color="#ff0000" size="3"><strong><font size="2">char * str是存储在全局静态存储区，所以，虽然是局部变量但函数返回后依然可以拿到正确的值！<br /></font></strong></span>char str[] 是存储在栈上的，local variable ，函数返回后，OS就收回空间了，就不复存在了，所以，拿不到正确的结果！</p>
<p>&nbsp;</p>
<p style="text-indent: 2em">&nbsp;char str[]="name"；与char str[5]；str="name" 的不同之处在哪，能不能从内存分配的角度讲一讲，我知道数组名字是一个常量地址（指针），第一个为什么对，第二个为什么错？</p>
<p>&nbsp;</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二个先定义了一个数组，要知道数组名str是数组分配到的空间的首地址，str="name"应该是等号两边类型不匹配的错误。一般的常量应该没有内存地址的，除非有某个变量指向了该常量。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #ff0000" color="#ff0000"> 数组名是地址常量，那么常量当然不允许被重新赋值。<br /></span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "name"是一个字符串常量他存储在常量存储区，只能用一个指针指向它却不允许改变：char*p;p="name";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般情况下char str[]="name"；数组是在栈上的空间由编译器分配，内容可以由用户改变。</p></div></div> <img src ="http://www.cppblog.com/X-LIN/aggbug/193850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/X-LIN/" target="_blank">林</a> 2012-10-25 18:40 <a href="http://www.cppblog.com/X-LIN/archive/2012/10/25/193850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>