﻿<?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/wholier/category/18366.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 26 Mar 2012 05:57:07 GMT</lastBuildDate><pubDate>Mon, 26 Mar 2012 05:57:07 GMT</pubDate><ttl>60</ttl><item><title>string::c_str()、string::c_data()及string与char *的正确转换 </title><link>http://www.cppblog.com/wholier/articles/166446.html</link><dc:creator>SunnySophie</dc:creator><author>SunnySophie</author><pubDate>Fri, 24 Feb 2012 11:04:00 GMT</pubDate><guid>http://www.cppblog.com/wholier/articles/166446.html</guid><wfw:comment>http://www.cppblog.com/wholier/comments/166446.html</wfw:comment><comments>http://www.cppblog.com/wholier/articles/166446.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wholier/comments/commentRss/166446.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wholier/services/trackbacks/166446.html</trackback:ping><description><![CDATA[<p>string::c_str的介绍:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c_str函数的返回值是const char*的，不能直接赋值给char*，所以就需要我们进行相应的操作转化，下面就是这一转化过程。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c++语言提供了两种字符串实现，其中较原始的一种只是字符串的c语言实现。与C语言的其他部分一样，它在c++的所有实现中可用，我们将这种实现提供的字符串对象，归为c-串，每个c-串char*类型的。<br />　　标准头文件&lt;cstring&gt;包含操作c-串的函数库。这些库函数表达了我们希望使用的几乎每种字符串操作。 当调用库函数，客户程序提供的是string类型参数，而库函数内部实现用的是c-串，因此需要将string对象，转化为char*对象，而c_str()提供了这样一种方法，它返回一个客户程序可读不可改的指向字符数组的指针。 例：</p>
<p>#include &lt;iostream&gt; <br />#include &lt;string&gt; <br />usingnamespace std; <br />void main() <br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string add_to="hello!";&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//std::cout&lt;&lt;add_to&lt;&lt;endl;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const string add_on="baby";&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const char*cfirst = add_to.c_str();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const char*csecond = add_on.c_str();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char*copy =newchar[strlen(cfirst) + strlen(csecond) +1];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy( copy, cfirst);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&lt;&lt;copy&lt;&lt;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//strcat( copy, csecond);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_to = copy;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete [] copy;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&lt;&lt;add_to&lt;&lt;std::endl;<br />}</p>
<p>简单的例子：<br />　　const char *c_str();<br />　　c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同.<br />　　这是为了与c语言兼容，在c语言中没有string类型，故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。<br />　　注意：一定要使用strcpy()函数 等来操作方法c_str()返回的指针<br />　　比如：最好不要这样:　　<br />&nbsp; 　 char* c;　　<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string s="1234";<br />&nbsp; 　 c = s.c_str(); 　　　//c最后指向的内容是垃圾，因为s对象被析构，其内容被处理（纠正：s对象的析构是在对指针c完成赋值操作之后进行的，故此处并没有错误）</p>
<p>　　应该这样用：<br />&nbsp;　 char c[20];　　<br />&nbsp;&nbsp;&nbsp;&nbsp; string s="1234";<br />&nbsp;　 strcpy(c,s.c_str());</p>
<p>　&nbsp; 这样才不会出错，c_str()返回的是一个临时指针，不能对其进行操作<br />　&nbsp; 再举个例子<br />　&nbsp; c_str() 以 char* 形式传回 string 内含字符串<br />　&nbsp; 如果一个函数要求char*参数，可以使用c_str()方法：</p>
<p>　&nbsp; string s ="Hello World!";　　<br />&nbsp;&nbsp;&nbsp;&nbsp; printf("%s", s.c_str()); //输出 "Hello World!"<br />　&nbsp; c_str在打开文件时的用处：当需要打开一个由用户自己输入文件名的文件时，可以这样写：ifstream in(st.c_str());。其中st是string类型，存放的即为用户输入的文件名。</p>
<p>&nbsp;</p>
<p>string::c_str()、string::c_data()的区别：</p>
<p>const value_type *c_str( ) const;<br />const value_type *data( ) const;<br />&nbsp;<br />data只是返回原始数据序列，没有保证会用traits::eos()，或者说'\0'来作字符串结束.&nbsp;&nbsp; 当然，可能多数实现都这样做了。&nbsp;&nbsp; </p>
<p>c_str是标准的做法，返回的char*, 一定指向一个合法的用'\0'终止的C兼容的字符串。&nbsp;&nbsp; <br />所以，如果需要C兼容的字符串，c_str是标准的做法，data并不保证所有STL的实现的一致性。</p>
<p>&nbsp;<br />你或许会问，c_str()的功能包含data()，那还需要data()函数干什么？看看源码：<br />const charT* c_str () const<br />{</p>
<p>&nbsp;&nbsp; if&nbsp; (length () == 0)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "";</p>
<p>&nbsp;&nbsp; terminate ();</p>
<p>&nbsp;&nbsp; return data ();</p>
<p>}<br />原来c_str()的流程是：先调用terminate()，然后在返回data()。因此如果你对效率要求比较高，而且你的处理又不一定需要以\0的方式结束，你最好选择data()。但是对于一般的C函数中，需要以const char*为输入参数，你就要使用c_str()函数。<br />对于c_str() data()函数，返回的数组都是由string本身拥有，千万不可修改其内容。其原因是许多string实现的时候采用了引用机制，也就是说，有可能几个string使用同一个字符存储空间。而且你不能使用sizeof(string)来查看其大小。详细的解释和实现查看Effective STL的条款15：小心string实现的多样性。<br />另外在你的程序中，只在需要时才使用c_str()或者data()得到字符串，每调用一次，下次再使用就会失效，如：<br />string strinfo("this is Winter");<br />...<br />//最好的方式是:<br />foo(strinfo.c_str());<br />//也可以这么用:<br />const char* pstr=strinfo.c_str();<br />foo(pstr);<br />//不要再使用了pstr了, 下面的操作已经使pstr无效了。<br />strinfo += " Hello!";<br />foo(pstr);//错误！<br />会遇到什么错误？当你幸运的时候pstr可能只是指向"this is Winter Hello!"的字符串，如果不幸运，就会导致程序出现其他问题，总会有一些不可遇见的错误。总之不会是你预期的那个结果。</p>
<p>&nbsp;</p>
<p><br />补充：string是C++类，所以尽量用C++的函数操作string类。对应的是标准C和char *.<br /></p><img src ="http://www.cppblog.com/wholier/aggbug/166446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wholier/" target="_blank">SunnySophie</a> 2012-02-24 19:04 <a href="http://www.cppblog.com/wholier/articles/166446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CString,int,string,char*之间的转换</title><link>http://www.cppblog.com/wholier/articles/166445.html</link><dc:creator>SunnySophie</dc:creator><author>SunnySophie</author><pubDate>Fri, 24 Feb 2012 10:51:00 GMT</pubDate><guid>http://www.cppblog.com/wholier/articles/166445.html</guid><wfw:comment>http://www.cppblog.com/wholier/comments/166445.html</wfw:comment><comments>http://www.cppblog.com/wholier/articles/166445.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wholier/comments/commentRss/166445.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wholier/services/trackbacks/166445.html</trackback:ping><description><![CDATA[string 转 CString<br />CString.format(&#8221;%s&#8221;, string.c_str());<br /><br />char 转 CString<br />CString.format(&#8221;%s&#8221;, char*);<br /><br />char 转 string<br />string s(char *);<br /><br />string 转 char *<br />char *p = string.c_str();<br /><br />CString 转 string<br />string s(CString.GetBuffer());<br /><br />1，string -&gt; CString<br />CString.format(&#8221;%s&#8221;, string.c_str());<br />用c_str()确实比data()要好。<br />2，char -&gt; string<br />string s(char *);<br />你的只能初始化，在不是初始化的地方最好还是用assign()。<br />3,CString -&gt; string<br />string s(CString.GetBuffer());<br />GetBuffer()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间。<br /><br />《C++标准函数库》中说的有三个函数可以将字符串的内容转换为字符数组和C&#8212;string<br />1.data(),返回没有&#8221;\0&#8220;的字符串数组<br />2,c_str()，返回有&#8221;\0&#8220;的字符串数组<br />3，copy()<br />&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />CString与int、char*、char[100]之间的转换- -<br />&nbsp;<br />CString互转int<br />将字符转换为整数，可以使用atoi、_atoi64或atol。<br />而将数字转换为CString变量，可以使用CString的Format函数。如<br />CString s;<br />int i = 64;<br />s.Format(&#8221;%d&#8221;, i)<br />Format函数的功能很强，值得你研究一下。<br />void CStrDlg::OnButton1()<br />{<br />// TODO: Add your control notification handler code here<br />CString<br />ss=&#8221;1212.12〃;<br />int temp=atoi(ss);<br />CString aa;<br />aa.Format(&#8221;%d&#8221;,temp);<br />AfxMessageBox(&#8221;var is &#8221; + aa);<br />}<br />sart.Format(&#8221;%s&#8221;,buf);<br />CString互转char*<br />///char * TO cstring<br />CString strtest;<br />char * charpoint;<br />charpoint=&#8221;give string a value&#8221;;<br />strtest=charpoint;<br />///cstring TO char *<br />charpoint=strtest.GetBuffer(strtest.GetLength());<br />标准C里没有string,char *==char []==string<br />可以用CString.Format(&#8221;%s&#8221;,char *)这个方法来将char *转成CString。要把CString转成char *，用操作符（LPCSTR）CString就可以了。<br />CString转换 char[100]<br />char a[100];<br />CString str(&#8221;aaaaaa&#8221;);<br />strncpy(a,(LPCTSTR)str,sizeof(a));<br />Trackback: <a href="http://tb.blog.csdn.net/TrackBack.aspx?PostId=1570001">http://tb.blog.csdn.net/TrackBack.aspx?PostId=1570001</a><br />&nbsp;<br />(一) 概述<br />string和CString均是字符串模板类，string为标准模板类（STL）定义的字符串类，已经纳入C++标准之中；<br />CString（typedef CStringT &gt; CString）为Visual C++中最常用的字符串类，继承自CSimpleStringT类，主要应用在MFC和ATL编程中，主要数据类型有char(应用于ANSI)，wchar_t(unicode)，TCHAR(ANSI与unicode均可)；<br />char*为C编程中最常用的字符串指针，一般以&#8217;\0&#8242;为结束标志；<br />(二) 构造<br />string是方便的，可以从几乎所有的字符串构造而来，包括CString和char*；<br />CString次之，可以从基本的一些字符串变量构造而来，包括char*等；<br />char*没有构造函数，仅可以赋值；<br />举例：<br />char* psz = &#8220;joise&#8221;;<br />CString cstr( psz );<br />string str( cstr );<br />(三) 运算符重载<br />a) perator=<br />string是最方便的，几乎可以直接用所有的字符串赋值，包括CString和char*；<br />CString次之，可以直接用些基本的字符串赋值，包括char*等；<br />char*只能由指针赋值，并且是极危险的操作，建议使用strcpy或者memcpy，而且char*在声明的时候如未赋初值建议先设为NULL，以避免野指针，令你抓狂；<br />举例：<br />char *psz = NULL;<br />psz = new char[10]; //当然，以上的直接写成char *psz = new char[10];也是一样<br />memset( psz, 0, 10 );<br />strcpy( psz, &#8220;joise&#8221; );<br />CString cstr;<br />cstr = psz;<br />string str;<br />str = psz;<br />str = cstr;<br />delete []psz;<br />b) operator+<br />string与CString差不多，可以直接与char*进行加法，但不可以相互使用+运算符，即string str = str + cstr是非法的，须转换成char*；<br />char*没有+运算，只能使用strcat把两个指针连在一起；<br />举例：<br />char* psz = &#8220;joise&#8221;;<br />CString cstr = psz;<br />cstr = cstr + psz;<br />string str = psz;<br />str = str + str + psz;<br />strcat( psz, psz );<br />strcat( psz, cstr );//合法<br />strcat( psz, str );//非法，由此可见，CString可自动转换为const char*，而string不行<br />c) operator +=<br />string是最强大的，几乎可以与所有的字符串变量+=，包括CString和char*；<br />CString次之，可以与基本的一些字符串变量进行+=而来，包括char*等；<br />char*没有+=运算符，只能使用strcat把两个指针连在一起；<br />d) operator[]<br />CString最好，当越界时会抛出断言异常；<br />string与char*下标越界结果未定义；<br />举例：<br />char* psz = &#8220;joise&#8221;;<br />CString cstr = psz;<br />cout &lt;&lt; cstr[8];<br />string str = psz;<br />cout &lt;&lt; str[8];<br />cout &lt;&lt; psz[8];<br />e) perator== 、operator!=、operator&gt; 、operator&lt; 、operator&gt;= 、perator&lt;=<br />CString与string之间不可以进行比较，但均可以与char*进行比较，并且比较的是值，而不是地址；<br />cout &lt;&lt; ( psz == cstr );<br />cout &lt;&lt; ( psz == str );<br />cout &lt;&lt; ( str == psz );<br />cout &lt;&lt; ( cstr == psz );//以上代码返回均为1<br />(四) 常用算法<br />a) 查找<br />作用 char* string CString<br />查找指定值 strchr<br />strstr<br />strrstr<br />strspn find Find<br />第一个匹配的值 fild_first_of FindOneOf 从后面开始查找 ReserveFind 指定匹配方式 find_if<br />注：find_if中是把范围内的值挨个代入匹配函数直至返回true<br />b) 比较<br />作用 char* string CString 查找指定值(区分大小写) strcmp<br />strncmp<br />strcoll<br />_strncoll operator&lt;<br />operator&gt;<br />operator&lt;=<br />operator&gt;=<br />operator==<br />operator!= Collate<br />Compare 查找指定值(不区分大小写) _stricmp<br />_strnicmp<br />_str违规广告<br />_strn违规广告 CollateNoCase<br />CompareNoCas<br />注：返回值如果&lt;0则前面的值小于后面的值，反之亦然<br />c) 替换<br />作用 char* string CString 查找指定值 _strset<br />_strnset<br />replace<br />replace_copy<br />replace_copy_if<br />replace_if Replace<br />d) 插入<br />作用 char* string CString 查找指定值 insert Insert<br />&nbsp; <br />e) 增加 作用 char* string CString 动态增加值 strcat push<br />append Append<br />AppendChar<br />AppendFormat<br />f) 截取<br />作用 char* string CString 得到部分值 用下标操作 substr Left<br />Mid<br />Right<br />Truncate<br />g) 移除<br />作用 char* string CString 移除部份值 remove Remove 移除空白值 RemoveBlanks<br />注：此为ATL提供，非C函数 remove_if Trim<br />TrimLeft<br />TrimRig<br />h) 转换大小写<br />作用 char* string CString 转换大小写 _strlwr<br />_strupr MakeLower<br />MakeUpper<br />i) 与其他类型转换<br />作用 char* string CString 转化为数字 atoi<br />atod<br />atof Format 转化为char* c_str<br />GetBuffer<br />GetBufferSetLen<br />j) 格式化<br />作用 char* string CString 格式化 sprintf Format<br />k) 得到长度<br />作用 char* string CString<br />得到长度 strlen length GetLength 得到大小 size GetAllocLength<br />l) 判断为空<br />作用 char* string CString 判断是否为空 判断是否==NULL或者第一个字符是否是&#8217;\0&#8242; empty IsEmpty<br />m) 重定义大小<br />作用 char* string CString 重定义大小 realloc<br />new resize GetBufferSetLength<br />n) 释放资源<br />作用 char* string CString 释放 free<br />delete (delete[]) ReleaseBuffer<br />ReleaseBufferSetLength<br />(五) 安全性&gt;<br />CString &gt; string &gt; char*；<br />(六) 灵活性<br />CString &gt; string &gt;char*；<br />(七) 可移植性<br />char* = string &gt; CString <img src ="http://www.cppblog.com/wholier/aggbug/166445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wholier/" target="_blank">SunnySophie</a> 2012-02-24 18:51 <a href="http://www.cppblog.com/wholier/articles/166445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于typedef的用法总结 </title><link>http://www.cppblog.com/wholier/articles/162050.html</link><dc:creator>SunnySophie</dc:creator><author>SunnySophie</author><pubDate>Tue, 13 Dec 2011 11:55:00 GMT</pubDate><guid>http://www.cppblog.com/wholier/articles/162050.html</guid><wfw:comment>http://www.cppblog.com/wholier/comments/162050.html</wfw:comment><comments>http://www.cppblog.com/wholier/articles/162050.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wholier/comments/commentRss/162050.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wholier/services/trackbacks/162050.html</trackback:ping><description><![CDATA[不管实在C还是C++代码中，typedef这个词都不少见，当然出现频率较高的还是在C代码中。typedef与#define有些相似，但更多的是不同，特别是在一些复杂的用法上，就完全不同了，看了网上一些C/C++的学习者的博客，其中有一篇关于typedef的总结还是很不错，由于总结的很好，我就不加修改的引用过来了，以下是引用的内容(<span style="color: red">红色部分是我自己写的内容</span>)。 
<p><strong><span style="font-family: 宋体">用途一：</span></strong></p>
<p align="left"><span style="font-family: 宋体">定义一种类型的别名，而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如：</span></p>
<p align="left">char* pa, pb;&nbsp;// <span style="font-family: 宋体">这多数不符合我们的意图，它只声明了一个指向字符变量的指针，</span></p>
<p align="left">// <span style="font-family: 宋体">和一个字符变量；</span></p>
<p align="left"><span style="font-family: 宋体">以下则可行：</span></p>
<p align="left">typedef char* PCHAR; </p>
<p align="left">PCHAR pa, pb;&nbsp;&nbsp;</p>
<p style="color: red" align="left">这种用法很有用，特别是char* pa, pb的定义，初学者往往认为是定义了两个字符型指针，其实不是，而用typedef char* PCHAR就不会出现这样的问题，减少了错误的发生。</p>
<p style="color: red" align="left"><span style="color: #333300"><span style="color: #333300">用途二:<br />用在旧的C代码中，帮助struct。以前的代码中，声明struct新对象时，必须要带上</span></span><span style="color: #003300"><span style="color: #003300">struct，即形式为： struct 结构名对象名，如：</span></span></p>
<p><font face="Verdana">struct tagPOINT1</font></p>
<p><font face="Verdana">&nbsp;{<br />&nbsp;&nbsp;&nbsp; int x; </font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; int y; <br />};</font></p>
<p><font face="Verdana">struct tagPOINT1 p1;</font></p>
<p><font face="Verdana">而在C++中，则可以直接写：结构名对象名，即：tagPOINT1 p1;</font></p>
<p><font face="Verdana">typedef struct tagPOINT<br />{<br />&nbsp;&nbsp;&nbsp; int x;</font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; int y;<br />}POINT;</font></p>
<p><font face="Verdana">POINT p1; // 这样就比原来的方式少写了一个struct，比较省事，尤其在大量使用的时</font></p>
<p><font face="Verdana">候,或许，在C++中，typedef的这种用途二不是很大，但是理解了它，对掌握以前的旧代</font></p>
<p><font face="Verdana">码还是有帮助的，毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。</font></p>
<p><font face="Verdana">用途三：</font></p>
<p><font face="Verdana">用typedef来定义与平台无关的类型。</font></p>
<p><font face="Verdana">比如定义一个叫 REAL 的浮点类型，在目标平台一上，让它表示最高精度的类型为：</font></p>
<p><font face="Verdana">typedef long double REAL;</font></p>
<p><font face="Verdana">在不支持 long double 的平台二上，改为：</font></p>
<p><font face="Verdana">typedef double REAL;</font></p>
<p><font face="Verdana">在连 double 都不支持的平台三上，改为：</font></p>
<p><font face="Verdana">typedef float REAL;</font></p>
<p><font face="Verdana">也就是说，当跨平台时，只要改下 typedef 本身就行，不用对其他源码做任何修改。</font></p>
<p><font face="Verdana">标准库就广泛使用了这个技巧，比如size_t。另外，因为typedef是定义了一种类型的新别名，不是简单的字符串替换，所以它比宏来得稳健。<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">&nbsp;这个优点在我们写代码的过程中可以减少不少代码量哦！</span></font></p>
<p><font face="Verdana"><span style="color: #ff0000"><span style="color: #003300"><span style="color: #003300">用途四： </span></span></p>
<p><span style="color: #003300"><span style="color: #003300">为复杂的声明定义一个新的简单的别名。方法是：在原来的声明里逐步用别名替换一部</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">分复杂声明，如此循环，把带变量名的部分留到最后替换，得到的就是原声明的最简化</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">版。举例：&nbsp; </span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;原声明：void (*b[10]) (void (*)());</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">变量名为b，先替换右边部分括号里的，pFunParam为别名一：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef void (*pFunParam)();</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">再替换左边的变量b，pFunx为别名二：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef void (*pFunx)(pFunParam);</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">原声明的最简化版：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">pFunx b[10];<br />&nbsp;<br />原声明：doube(*)() (*e)[9];</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">变量名为e，先替换左边部分，pFuny为别名一：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef double(*pFuny)();</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">再替换右边的变量e，pFunParamy为别名二</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef pFuny (*pFunParamy)[9];</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">原声明的最简化版：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">pFunParamy e;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">理解复杂声明可用的&#8220;右左法则&#8221;：从变量名看起，先往右，再往左，碰到一个圆括号</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">就调转阅读的方向；括号内分析完就跳出括号，还是按先右后左的顺序，如此循环，直</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">到整个声明分析完。举例：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">int (*func)(int *p);</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">首先找到变量名func，外面有一对圆括号，而且左边是一个*号，这说明func是一个指针</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">；然后跳出这个圆括号，先看右边，又遇到圆括号，这说明(*func)是一个函数，所以</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">func是一个指向这类函数的指针，即函数指针，这类函数具有int*类型的形参，返回值</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">类型是int。</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">int (*func[5])(int *);</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">func右边是一个[]运算符，说明func是具有5个元素的数组；func的左边有一个*，说明</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">func的元素是指针（注意这里的*不是修饰func，而是修饰func[5]的，原因是[]运算符</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">优先级比*高，func先跟[]结合）。跳出这个括号，看右边，又遇到圆括号，说明func数</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">组的元素是函数类型的指针，它指向的函数具有int*类型的形参，返回值类型为int。</span></span></p>
<p><span style="color: #003300"><span style="color: #003300"><span style="color: #ff0000"><span style="color: #ff0000">这种用法是比较复杂的，出现的频率也不少，往往在看到这样的用法却不能理解，相信以上的解释能有所帮助。</span></span></span></span></p>
<p><span style="color: #003300"><span style="color: #003300">*****以上为参考部分，以下为本人领悟部分*****</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">使用示例：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">1.比较一：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">#include &lt;iostream&gt;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">using namespace std;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef int (*A) (char, char);</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">int ss(char a, char b)<br />{<br />&nbsp;&nbsp;&nbsp; cout&lt;&lt;"功能1"&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; cout&lt;&lt;a&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; cout&lt;&lt;b&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; return 0;<br />}<br />&nbsp;<br />int bb(char a, char b)<br />{</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; cout&lt;&lt;"功能2"&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; cout&lt;&lt;b&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; cout&lt;&lt;a&lt;&lt;endl;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; return 0;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">}</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">void main()<br />{</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; A a;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a = ss;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a('a','b');</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a = bb;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a('a', 'b');<br />}</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">2.比较二：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef int (A) (char, char);</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">void main()<br />{</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; A *a;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a = ss;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a('a','b');</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a = bb;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;&nbsp;&nbsp; a('a','b');<br />}<br />&nbsp;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">两个程序的结果都一样：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">功能1</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">a</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">b</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">功能2</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">b</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">a</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">&nbsp;</span></span></p>
<p><span style="color: #003300"></span><span style="color: #003300"><span style="color: #003300">*****以下是参考部分*****</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">参考自：http://blog.hc360.com/portal/personShowArticle.do?articleId=57527</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef 与 #define的区别：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">案例一：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">通常讲，typedef要比#define要好，特别是在有指针的场合。请看例子：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef char *pStr1;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">#define pStr2 char *;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">pStr1 s1, s2;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">pStr2 s3, s4;<br />在上述的变量定义中，s1、s2、s3都被定义为char *，而s4则定义成了char，不是我们</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">所预期的指针变量，根本原因就在于#define只是简单的字符串替换而typedef则是为一</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">个类型起新名字。</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">案例二：</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">下面的代码中编译器会报一个错误，你知道是哪个语句错了吗？</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">typedef char * pStr;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">char string[4] = "abc";</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">const char *p1 = string;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">const pStr p2 = string;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">p1++;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">p2++;</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">　　是p2++出错了。这个问题再一次提醒我们：typedef和#define不同，它不是简单的</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">const long x本质上没有区别，都是对变量进行只读限制，只不过此处变量p2的数据类</span></span></p>
<p><span style="color: #003300"><span style="color: #003300">型是我们自己定义的而不是系统固有类型而已。因此，const pStr p2的含义是：限定数</span></span></p>
<p><span style="color: #003300">据类型为char *的变量p2为只读，因此p2++错误。<br /><span style="color: #ff0000">虽然作者在这里已经解释得很清楚了，可我在这个地方仍然还是糊涂的，真的希望哪位高手能帮忙指点一下，特别是这一句&#8220;只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已&#8221;，难道自己定义的类型前面用const修饰后，就不能执行更改运算，而系统定义的类型却可以？<br /></span></span></p></span></font><img src ="http://www.cppblog.com/wholier/aggbug/162050.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wholier/" target="_blank">SunnySophie</a> 2011-12-13 19:55 <a href="http://www.cppblog.com/wholier/articles/162050.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>