<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Felix021]]></title> 
<link>https://www.felix021.com/blog/index.php</link> 
<description><![CDATA[So far so good]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Felix021]]></copyright>
<ttl>10</ttl>
<item>
    <title><![CDATA[[翻译] 如何阅读复杂的C定义/声明]]></title> 
    <link>https://www.felix021.com/blog/read.php?2072</link>
    <description><![CDATA[翻译自：How To Read C Declarations <a href="/blog/read.php?1482" target="_blank">英文原文</a><br/>p.s. 以前还真没注意到这篇文章最后提到的vtable是啥意思……<br/><br/>就算是非常有经验的C程序员，也对那些比简单数组/指针更复杂一些的声明感到头疼。比如说，下面这个是一个指针的数组，还是一个数组的指针？<div class="code">int *a&#91;10&#93;;</div><br/>下面这货到底是什么？<div class="code">int (*(*vtable)&#91;&#93;)();</div><br/>当然了，这货是一个指针，指向一个数组，这个数组的每个元素是一个指针，指向一个函数，函数的返回值类型是int&nbsp; :)<br/><br/>这篇短文希望能够教会你一个非常简单地读懂复杂声明的方法。我99%肯定我在80年代读过这篇，但是不记得具体是在什么地方读到的了。我怀疑是我自己发现这个的（尽管我总会被计算机语言结构和神秘的事物搞得很兴奋）。然而我的确记得，能够写出一个程序，将任何声明转换成英语。<br/><br/>== 黄金法则 ==<br/><br/>这个法则是这样说的：<div class="quote"><div class="quote-title">引用</div><div class="quote-content">从标识符开始（或者最内层的结构，如果不存在标识符的话，通常出现于函数指针），首先向右看，直到遇到 ) 括号或者结束，看到什么就说出来；然后向左看，直到遇到 ( 括号或者回到行首，看到什么就说出来。跳出一层括号，重复上述过程：右看看，说出来；左看看，说出来。直到你说出变量的类型或者返回值（针对函数指针），也就表示你把声明都读完了。</div></div><br/><br/>最简单的情况是这样的：<div class="code">int i;</div><br/>从 i 开始，你向右看，啥都没看到；然后就向左看，看到了int，说出来：i是一个int。<br/><br/>然后看个复杂一点的：<div class="code">int *a&#91;3&#93;;</div><br/>从 a 开始：向右看，说“是一个包含3个元素的数组”；向左看，说“数组的每个元素是指针”；向右看，啥都没；向左看，说“指针指向int”。综合起来就是: a 是一个包含3个元素的数组，每个元素是一个指针，指向int。<br/><br/>加上一对括号让它看起来更怪异点儿：<div class="code">int (*a)&#91;3&#93;;</div><br/>像在普通表达式中一样，括号改变了阅读/计算的顺序。从 a 开始：向右看，遇到括号了，往回；向左看，说“是一个指针”，遇到(括号，跳出来；向右看，[3]，说“指向一个包含3个元素的数组”；向左看，int，说“数组的每个元素是int”。综合起来：a是一个指针，指向一个包含3个元素的数组，数组的每个元素是一个int。<br/><br/>好，再来看看这个：<div class="code">extern int *foo();</div><br/>赞，你说：foo是一个函数，返回一个指针，指向int。<br/><br/>接下来跳一步：就像我们可以定义一个指向int的指针，我们也可以定义一个指向函数的指针。在这种情况下，不需要extern了（因为不是函数的前向引用声明），而是一个变量的定义。这是一个基本的函数指针：<div class="code">int (*foo)();</div><br/>从foo开始：向右看，遇到括号，往回；向左看，*，说“是一个指针”，遇到左括号，跳出来；向右看，()，说“指向一个函数”；向左看，int，说“函数返回int”。综合起来：foo是一个指针，指向一个函数，函数返回int。<br/><br/>下面是一个数组，每个元素是一个指针，指向函数，函数返回int：<div class="code">int (*Object_vtable&#91;&#93;)();</div><br/><br/>你还需要最后一个，诡异的难以置信的声明：<div class="code">int (*(*vtable)&#91;&#93;)();</div><br/>这是一个指针，指向一个数组，数组的每个元素是个指针，指向一个函数，函数的返回值是int。发现了吗？这货就是上面那个object_vtable的指针，也就是你定义的每一个对象需要的虚函数表(vtable)的指针。<br/><br/>这个指向vtable的指针是一个vtable的地址，例如，&Truck_vtable （就是某个Truck类的实例虚函数表的指针）。<br/><br/>== 总结 ==<br/><br/>接下来的例子总结了所有C++为了实现多态性所建造的虚函数表需要的所有情形（就像最初的C Front - C++转C翻译器）。<div class="code">int *ptr_to_int; <br/>int *func_returning_ptr_to_int();<br/>int (*ptr_to_func_returning_int)();<br/>int (*array_of_ptr_to_func_returning_int&#91;&#93;)();<br/>int (*(*ptr_to_an_array_of_ptr_to_func_returning_int)&#91;&#93;)();</div>]]></description>
    <pubDate>Sun, 08 Apr 2012 11:32:15 +0000</pubDate> 
    <category><![CDATA[程序设计]]></category>
    <author>felix021 &lt;i[#at]felix021.com&gt;</author>
    <guid>https://www.felix021.com/blog/read.php?2072</guid> 
</item>
<item>
    <title><![CDATA[[评论] [翻译] 如何阅读复杂的C定义/声明]]></title> 
    <link>https://www.felix021.com/blog/read.php?2072#blogcomment</link>
    <description><![CDATA[]]></description>
    <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
    <category><![CDATA[评论]]></category>
    <author> &lt;user@domain.com&gt;</author>
    <guid>https://www.felix021.com/blog/read.php?2072#blogcomment</guid> 
</item>

</channel>
</rss>