<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>GCCFeli.cn &#187; Linux</title> <atom:link href="http://gccfeli.cn/tag/linux/feed" rel="self" type="application/rss+xml" /><link>http://gccfeli.cn</link> <description></description> <lastBuildDate>Thu, 14 Jul 2011 08:18:00 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.1</generator> <atom:link rel='hub' href='http://gccfeli.cn/?pushpress=hub'/> <item><title>Linux 内核使用的 GNU C 扩展</title><link>http://gccfeli.cn/2008/07/linux-gnu-c-extension.html</link> <comments>http://gccfeli.cn/2008/07/linux-gnu-c-extension.html#comments</comments> <pubDate>Wed, 02 Jul 2008 07:26:51 +0000</pubDate> <dc:creator>Felicia</dc:creator> <category><![CDATA[Linux]]></category> <category><![CDATA[转载]]></category> <category><![CDATA[GNU C]]></category> <category><![CDATA[扩展]]></category><guid
isPermaLink="false">http://www.gccfeli.cn/archives/158.html</guid> <description><![CDATA[<p>GNU C 是一个功能非常强大的跨平台 C 编译器，它对 C 语言提供了很多扩展，这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。本文把支持 GNU 扩展的 C 语言称为 GNU C。</p><p>Linux 内核代码使用了大量的 GNU C 扩展，以至于能够编译 Linux 内核的唯一编译器是 GNU CC，以前甚至出现过编译 Linux 内核要使用特殊的 GNU CC 版本的情况。本文是对 Linux 内核使用的 GNU C 扩展的一个汇总，希望当你读内核源码遇到不理解的语法和语义时，能从本文找到一个初步的解答，更详细的信息可以查看gcc.info。文中的例子取自 Linux 2.4.18。<br
/> <span
class="readmore"><a
href="http://gccfeli.cn/2008/07/linux-gnu-c-extension.html" title="Linux 内核使用的 GNU C 扩展">阅读全文（6285字）</a></span>]]></description> <content:encoded><![CDATA[<p>GNU C 是一个功能非常强大的跨平台 C 编译器，它对 C 语言提供了很多扩展，这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。本文把支持 GNU 扩展的 C 语言称为 GNU C。</p><p>Linux 内核代码使用了大量的 GNU C 扩展，以至于能够编译 Linux 内核的唯一编译器是 GNU CC，以前甚至出现过编译 Linux 内核要使用特殊的 GNU CC 版本的情况。本文是对 Linux 内核使用的 GNU C 扩展的一个汇总，希望当你读内核源码遇到不理解的语法和语义时，能从本文找到一个初步的解答，更详细的信息可以查看gcc.info。文中的例子取自 Linux 2.4.18。<br
/> <span
id="more-158"></span></p><h3>语句表达式</h3><p>GNU C 把包含在括号中的复合语句看做是一个表达式，称为语句表达式，它可以出现在任何允许表达式的地方，你可以在语句表达式中使用循环、局部变量等，原本只能在复合语句中使用。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">159</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">min_t</span><span
class="hl-brackets">(</span><span
class="hl-identifier">type</span><span
class="hl-code">,</span><span
class="hl-identifier">x</span><span
class="hl-code">,</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code"> <br
/></span><span
class="hl-number">160</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-brackets">({</span><span
class="hl-code"> </span><span
class="hl-identifier">type</span><span
class="hl-code"> </span><span
class="hl-identifier">__x</span><span
class="hl-code"> = </span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">; </span><span
class="hl-identifier">type</span><span
class="hl-code"> </span><span
class="hl-identifier">__y</span><span
class="hl-code"> = </span><span
class="hl-brackets">(</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code">; </span><span
class="hl-identifier">__x</span><span
class="hl-code"> &amp;</span><span
class="hl-identifier">lt</span><span
class="hl-code">; </span><span
class="hl-identifier">__y</span><span
class="hl-code"> ? </span><span
class="hl-identifier">__x</span><span
class="hl-code">: </span><span
class="hl-identifier">__y</span><span
class="hl-code">; </span><span
class="hl-brackets">})</span><span
class="hl-code"><br
/>++++ </span><span
class="hl-identifier">net</span><span
class="hl-code">/</span><span
class="hl-identifier">ipv4</span><span
class="hl-code">/</span><span
class="hl-identifier">tcp_output</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">654</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">int</span><span
class="hl-code"> </span><span
class="hl-identifier">full_space</span><span
class="hl-code"> = </span><span
class="hl-identifier">min_t</span><span
class="hl-brackets">(</span><span
class="hl-types">int</span><span
class="hl-code">, </span><span
class="hl-identifier">tp</span><span
class="hl-code">-&amp;</span><span
class="hl-identifier">gt</span><span
class="hl-code">;</span><span
class="hl-identifier">window_clamp</span><span
class="hl-code">, </span><span
class="hl-identifier">tcp_full_space</span><span
class="hl-brackets">(</span><span
class="hl-identifier">sk</span><span
class="hl-brackets">))</span><span
class="hl-code">;</span></div></div></div><p>复合语句的最后一个语句应该是一个表达式，它的值将成为这个语句表达式的值。<br
/> 这里定义了一个安全的求最小值的宏，在标准 C 中，通常定义为:</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-prepro">#define</span><span
class="hl-code"> </span><span
class="hl-identifier">min</span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-code">,</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code"> &amp;</span><span
class="hl-identifier">lt</span><span
class="hl-code">; </span><span
class="hl-brackets">(</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code"> ? </span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code"> : </span><span
class="hl-brackets">(</span><span
class="hl-identifier">y</span><span
class="hl-brackets">))</span></div></div></div><p>这个定义计算 x 和 y 分别两次，当参数有副作用时，将产生不正确的结果，使用语句表达式只计算参数一次，避免了可能的错误。语句表达式通常用于宏定义。</p><h3>Typeof</h3><p>使用前一节定义的宏需要知道参数的类型，利用 typeof 可以定义更通用的宏，不必事先知道参数的类型，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">141</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">min</span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-code">,</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code"> </span><span
class="hl-brackets">({</span><span
class="hl-code"> <br
/></span><span
class="hl-number">142</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">const</span><span
class="hl-code"> </span><span
class="hl-identifier">typeof</span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code"> </span><span
class="hl-identifier">_x</span><span
class="hl-code"> = </span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">;&nbsp; &nbsp; &nbsp; &nbsp;<br
/></span><span
class="hl-number">143</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">const</span><span
class="hl-code"> </span><span
class="hl-identifier">typeof</span><span
class="hl-brackets">(</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code"> </span><span
class="hl-identifier">_y</span><span
class="hl-code"> = </span><span
class="hl-brackets">(</span><span
class="hl-identifier">y</span><span
class="hl-brackets">)</span><span
class="hl-code">;&nbsp; &nbsp; &nbsp; &nbsp;<br
/></span><span
class="hl-number">144</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-brackets">(</span><span
class="hl-types">void</span><span
class="hl-brackets">)</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-code">&amp;</span><span
class="hl-identifier">amp</span><span
class="hl-code">;</span><span
class="hl-identifier">_x</span><span
class="hl-code"> == &amp;</span><span
class="hl-identifier">amp</span><span
class="hl-code">;</span><span
class="hl-identifier">_y</span><span
class="hl-brackets">)</span><span
class="hl-code">;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br
/></span><span
class="hl-number">145</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">_x</span><span
class="hl-code"> &amp;</span><span
class="hl-identifier">lt</span><span
class="hl-code">; </span><span
class="hl-identifier">_y</span><span
class="hl-code"> ? </span><span
class="hl-identifier">_x</span><span
class="hl-code"> : </span><span
class="hl-identifier">_y</span><span
class="hl-code">; </span><span
class="hl-brackets">})</span></div></div></div><p>这里 typeof(x) 表示 x 的值类型，第 142 行定义了一个与 x 类型相同的局部变量 _x 并初使化为 x，注意第 144 行的作用是检查参数 x 和 y 的类型是否相同。<br
/> typeof 可以用在任何类型可以使用的地方，通常用于宏定义。</p><h3>零长度数组</h3><p>GNU C 允许使用零长度数组，在定义变长对象的头结构时，这个特性非常有用。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">minix_fs</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">85</span><span
class="hl-code">: </span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">minix_dir_entry</span><span
class="hl-code"> </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">86</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__u16</span><span
class="hl-code"> </span><span
class="hl-identifier">inode</span><span
class="hl-code">;<br
/></span><span
class="hl-number">87</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">char</span><span
class="hl-code"> </span><span
class="hl-identifier">name</span><span
class="hl-brackets">[</span><span
class="hl-number">0</span><span
class="hl-brackets">]</span><span
class="hl-code">;<br
/></span><span
class="hl-number">88</span><span
class="hl-code">: </span><span
class="hl-brackets">}</span><span
class="hl-code">;</span></div></div></div><p>结构的最后一个元素定义为零长度数组，它不占结构的空间。在标准 C 中则需要定义数组长度为 1，分配时计算对象大小比较复杂。</p><h3>可变参数宏</h3><p>在 GNU C 中，宏可以接受可变数目的参数，就象函数一样，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">110</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">pr_debug</span><span
class="hl-brackets">(</span><span
class="hl-identifier">fmt</span><span
class="hl-code">,</span><span
class="hl-identifier">arg</span><span
class="hl-code">...</span><span
class="hl-brackets">)</span><span
class="hl-code"> <br
/></span><span
class="hl-number">111</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-identifier">KERN_DEBUG</span><span
class="hl-code"> </span><span
class="hl-identifier">fmt</span><span
class="hl-code">,##</span><span
class="hl-identifier">arg</span><span
class="hl-brackets">)</span></div></div></div><p>这里 arg 表示其余的参数，可以是零个或多个，这些参数以及参数之间的逗号构成 arg 的值，在宏扩展时替换 arg，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-identifier">pr_debug</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">%s:%d</span><span
class="hl-quotes">&quot;</span><span
class="hl-code">,</span><span
class="hl-identifier">filename</span><span
class="hl-code">,</span><span
class="hl-identifier">line</span><span
class="hl-brackets">)</span></div></div></div><p>扩展为</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">&amp;lt;7&amp;gt;</span><span
class="hl-quotes">&quot;</span><span
class="hl-code"> </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">%s:%d</span><span
class="hl-quotes">&quot;</span><span
class="hl-code">, </span><span
class="hl-identifier">filename</span><span
class="hl-code">, </span><span
class="hl-identifier">line</span><span
class="hl-brackets">)</span></div></div></div><p>使用 ## 的原因是处理 arg 不匹配任何参数的情况，这时 arg 的值为空，GNU C 预处理器在这种特殊情况下，丢弃 ## 之前的逗号，这样</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-identifier">pr_debug</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">success!n</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)</span></div></div></div><p>扩展为</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">&amp;lt;7&amp;gt;</span><span
class="hl-quotes">&quot;</span><span
class="hl-code"> </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">success!n</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)</span></div></div></div><p>注意最后没有逗号。</p><h3>标号元素</h3><p>标准 C 要求数组或结构变量的初使化值必须以固定的顺序出现，在 GNU C 中，通过指定索引或结构域名，允许初始化值以任意顺序出现。指定数组索引的方法是在初始化值前写 &#8216;[INDEX] =&#8217;，要指定一个范围使用 &#8216;[FIRST ... LAST] =&#8217; 的形式，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">+++++ </span><span
class="hl-identifier">arch</span><span
class="hl-code">/</span><span
class="hl-identifier">i386</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">/</span><span
class="hl-identifier">irq</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">1079</span><span
class="hl-code">: </span><span
class="hl-types">static</span><span
class="hl-code"> </span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">long</span><span
class="hl-code"> </span><span
class="hl-identifier">irq_affinity</span><span
class="hl-code"> </span><span
class="hl-brackets">[</span><span
class="hl-identifier">NR_IRQS</span><span
class="hl-brackets">]</span><span
class="hl-code"> = </span><span
class="hl-brackets">{</span><span
class="hl-code"> </span><span
class="hl-brackets">[</span><span
class="hl-number">0</span><span
class="hl-code"> ... </span><span
class="hl-identifier">NR_IRQS</span><span
class="hl-code">-</span><span
class="hl-number">1</span><span
class="hl-brackets">]</span><span
class="hl-code"> = ~</span><span
class="hl-number">0</span><span
class="hl-identifier">UL</span><span
class="hl-code"> </span><span
class="hl-brackets">}</span><span
class="hl-code">;</span></div></div></div><p>将数组的所有元素初使化为 ~0UL，这可以看做是一种简写形式。</p><p>要指定结构元素，在元素值前写 &#8216;FIELDNAME:&#8217;，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">fs</span><span
class="hl-code">/</span><span
class="hl-identifier">ext2</span><span
class="hl-code">/</span><span
class="hl-identifier">file</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">41</span><span
class="hl-code">: </span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">file_operations</span><span
class="hl-code"> </span><span
class="hl-identifier">ext2_file_operations</span><span
class="hl-code"> = </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">42</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">llseek</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">generic_file_llseek</span><span
class="hl-code">,<br
/></span><span
class="hl-number">43</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">read</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">generic_file_read</span><span
class="hl-code">,<br
/></span><span
class="hl-number">44</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">write</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">generic_file_write</span><span
class="hl-code">,<br
/></span><span
class="hl-number">45</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">ioctl</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">ext2_ioctl</span><span
class="hl-code">,<br
/></span><span
class="hl-number">46</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">mmap</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">generic_file_mmap</span><span
class="hl-code">,<br
/></span><span
class="hl-number">47</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">open</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">generic_file_open</span><span
class="hl-code">,<br
/></span><span
class="hl-number">48</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">release</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">ext2_release_file</span><span
class="hl-code">,<br
/></span><span
class="hl-number">49</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">fsync</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">ext2_sync_file</span><span
class="hl-code">,<br
/></span><span
class="hl-number">50</span><span
class="hl-code"> </span><span
class="hl-brackets">}</span><span
class="hl-code">;</span></div></div></div><p>将结构 ext2_file_operations 的元素 llseek 初始化为 generic_file_llseek，元素 read 初始化为 genenric_file_read，依次类推。我觉得这是 GNU C 扩展中最好的特性之一，当结构的定义变化以至元素的偏移改变时，这种初始化方法仍然保证已知元素的正确性。对于未出现在初始化中的元素，其初值为 0。</p><h3>Case 范围</h3><p>GNU C 允许在一个 case 标号中指定一个连续范围的值，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">arch</span><span
class="hl-code">/</span><span
class="hl-identifier">i386</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">/</span><span
class="hl-identifier">irq</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">1062</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">0</span><span
class="hl-code">' ... '</span><span
class="hl-number">9</span><span
class="hl-code">': </span><span
class="hl-identifier">c</span><span
class="hl-code"> -= '</span><span
class="hl-number">0</span><span
class="hl-code">'; </span><span
class="hl-reserved">break</span><span
class="hl-code">;<br
/></span><span
class="hl-number">1063</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-identifier">a</span><span
class="hl-code">' ... '</span><span
class="hl-identifier">f</span><span
class="hl-code">': </span><span
class="hl-identifier">c</span><span
class="hl-code"> -= '</span><span
class="hl-identifier">a</span><span
class="hl-code">'-</span><span
class="hl-number">10</span><span
class="hl-code">; </span><span
class="hl-reserved">break</span><span
class="hl-code">;<br
/></span><span
class="hl-number">1064</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-identifier">A</span><span
class="hl-code">' ... '</span><span
class="hl-identifier">F</span><span
class="hl-code">': </span><span
class="hl-identifier">c</span><span
class="hl-code"> -= '</span><span
class="hl-identifier">A</span><span
class="hl-code">'-</span><span
class="hl-number">10</span><span
class="hl-code">; </span><span
class="hl-reserved">break</span><span
class="hl-code">;</span></div></div></div><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">0</span><span
class="hl-code">' ... '</span><span
class="hl-number">9</span><span
class="hl-code">':</span></div></div></div><p>相当于</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">0</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">1</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">2</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">3</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">4</span><span
class="hl-code">':<br
/></span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">5</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">6</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">7</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">8</span><span
class="hl-code">': </span><span
class="hl-reserved">case</span><span
class="hl-code"> '</span><span
class="hl-number">9</span><span
class="hl-code">':</span></div></div></div><h3>声明的特殊属性</h3><p>GNU C 允许声明函数、变量和类型的特殊属性，以便手工的代码优化和更仔细的代码检查。要指定一个声明的属性，在声明后写</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-code"> </span><span
class="hl-identifier">ATTRIBUTE</span><span
class="hl-code"> </span><span
class="hl-brackets">))</span></div></div></div><p>其中 ATTRIBUTE 是属性说明，多个属性以逗号分隔。GNU C 支持十几个属性，这里介绍最常用的：</p><h4>noreturn</h4><p>属性 noreturn 用于函数，表示该函数从不返回。这可以让编译器生成稍微优化的代码，最重要的是可以消除不必要的警告信息比如未初使化的变量。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">47</span><span
class="hl-code">: # </span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">ATTRIB_NORET</span><span
class="hl-code">&nbsp; </span><span
class="hl-identifier">__attribute__</span><span
class="hl-brackets">((</span><span
class="hl-identifier">noreturn</span><span
class="hl-brackets">))</span><span
class="hl-code"><br
/>....<br
/></span><span
class="hl-number">61</span><span
class="hl-code">: </span><span
class="hl-identifier">asmlinkage</span><span
class="hl-code"> </span><span
class="hl-identifier">NORET_TYPE</span><span
class="hl-code"> </span><span
class="hl-types">void</span><span
class="hl-code"> </span><span
class="hl-identifier">do_exit</span><span
class="hl-brackets">(</span><span
class="hl-types">long</span><span
class="hl-code"> </span><span
class="hl-identifier">error_code</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/></span><span
class="hl-identifier">ATTRIB_NORET</span><span
class="hl-code">;</span></div></div></div><h4>format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)</h4><p>属性 format 用于函数，表示该函数使用 printf, scanf 或 strftime 风格的参数，使用这类函数最容易犯的错误是格式串与参数不匹配，指定 format 属性可以让编译器根据格式串检查参数类型。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">kernel</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code">?<br
/></span><span
class="hl-number">89</span><span
class="hl-code">: </span><span
class="hl-identifier">asmlinkage</span><span
class="hl-code"> </span><span
class="hl-types">int</span><span
class="hl-code"> </span><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-types">const</span><span
class="hl-code"> </span><span
class="hl-types">char</span><span
class="hl-code"> * </span><span
class="hl-identifier">fmt</span><span
class="hl-code">, ...</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/></span><span
class="hl-number">90</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">format</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-identifier">printf</span><span
class="hl-code">, </span><span
class="hl-number">1</span><span
class="hl-code">, </span><span
class="hl-number">2</span><span
class="hl-brackets">)))</span><span
class="hl-code">;</span></div></div></div><p>表示第一个参数是格式串，从第二个参数起根据格式串检查参数。</p><h4>unused</h4><p>属性 unused 用于函数和变量，表示该函数或变量可能不使用，这个属性可以避免编译器产生警告信息。</p><h4>section (&#8220;section-name&#8221;)</h4><p>属性 section 用于函数和变量，通常编译器将函数放在 .text 节，变量放在.data 或 .bss 节，使用 section 属性，可以让编译器将函数或变量放在指定的节中。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">init</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">78</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__init</span><span
class="hl-code">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.text.init</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">79</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__exit</span><span
class="hl-code">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">unused</span><span
class="hl-code">, </span><span
class="hl-identifier">__section__</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.text.exit</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">80</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__initdata</span><span
class="hl-code">&nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.data.init</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">81</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__exitdata</span><span
class="hl-code">&nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">unused</span><span
class="hl-code">, </span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.data.exit</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">82</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__initsetup</span><span
class="hl-code">&nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">unused</span><span
class="hl-code">,</span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.setup.init</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">83</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__init_call</span><span
class="hl-code">&nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">unused</span><span
class="hl-code">,</span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.initcall.init</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span><span
class="hl-code"><br
/></span><span
class="hl-number">84</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">__exit_call</span><span
class="hl-code">&nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">unused</span><span
class="hl-code">,</span><span
class="hl-identifier">__section__</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">.exitcall.exit</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)))</span></div></div></div><p>连接器可以把相同节的代码或数据安排在一起，Linux 内核很喜欢使用这种技术，例如系统的初始化代码被安排在单独的一个节，在初始化结束后就可以释放这部分内存。</p><h4>aligned (ALIGNMENT)</h4><p>属性 aligned 用于变量、结构或联合类型，指定变量、结构域、结构或联合的对齐量，以字节为单位，例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-reserved">asm</span><span
class="hl-code">-</span><span
class="hl-identifier">i386</span><span
class="hl-code">/</span><span
class="hl-identifier">processor</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">294</span><span
class="hl-code">: </span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">i387_fxsave_struct</span><span
class="hl-code"> </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">295</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">short</span><span
class="hl-code">&nbsp; </span><span
class="hl-identifier">cwd</span><span
class="hl-code">;<br
/></span><span
class="hl-number">296</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">short</span><span
class="hl-code">&nbsp; </span><span
class="hl-identifier">swd</span><span
class="hl-code">;<br
/></span><span
class="hl-number">297</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">short</span><span
class="hl-code">&nbsp; </span><span
class="hl-identifier">twd</span><span
class="hl-code">;<br
/></span><span
class="hl-number">298</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">short</span><span
class="hl-code">&nbsp; </span><span
class="hl-identifier">fop</span><span
class="hl-code">;<br
/></span><span
class="hl-number">299</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">long</span><span
class="hl-code">&nbsp; &nbsp; </span><span
class="hl-identifier">fip</span><span
class="hl-code">;<br
/></span><span
class="hl-number">300</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">long</span><span
class="hl-code">&nbsp; &nbsp; </span><span
class="hl-identifier">fcs</span><span
class="hl-code">;<br
/></span><span
class="hl-number">301</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">long</span><span
class="hl-code">&nbsp; &nbsp; </span><span
class="hl-identifier">foo</span><span
class="hl-code">;<br
/>......<br
/></span><span
class="hl-number">308</span><span
class="hl-code">: </span><span
class="hl-brackets">}</span><span
class="hl-code"> </span><span
class="hl-identifier">__attribute__</span><span
class="hl-code"> </span><span
class="hl-brackets">((</span><span
class="hl-identifier">aligned</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-number">16</span><span
class="hl-brackets">)))</span><span
class="hl-code">;</span></div></div></div><p>表示该结构类型的变量以 16 字节对齐。通常编译器会选择合适的对齐量，显示指定对齐通常是由于体系限制、优化等原因。</p><h4>packed</h4><p>属性 packed 用于变量和类型，用于变量或结构域时表示使用最小可能的对齐，用于枚举、结构或联合类型时表示该类型使用最小的内存。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-reserved">asm</span><span
class="hl-code">-</span><span
class="hl-identifier">i386</span><span
class="hl-code">/</span><span
class="hl-identifier">desc</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">51</span><span
class="hl-code">: </span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">Xgt_desc_struct</span><span
class="hl-code"> </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">52</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">short</span><span
class="hl-code"> </span><span
class="hl-identifier">size</span><span
class="hl-code">;<br
/></span><span
class="hl-number">53</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">unsigned</span><span
class="hl-code"> </span><span
class="hl-types">long</span><span
class="hl-code"> </span><span
class="hl-identifier">address</span><span
class="hl-code"> </span><span
class="hl-identifier">__attribute__</span><span
class="hl-brackets">((</span><span
class="hl-identifier">packed</span><span
class="hl-brackets">))</span><span
class="hl-code">;<br
/></span><span
class="hl-number">54</span><span
class="hl-code">: </span><span
class="hl-brackets">}</span><span
class="hl-code">;</span></div></div></div><p>域 address 将紧接着 size 分配。属性 packed 的用途大多是定义硬件相关的结构，使元素之间没有因对齐而造成的空洞。</p><h3>当前函数名</h3><p>GNU CC 预定义了两个标志符保存当前函数的名字，__FUNCTION__ 保存函数在源码中的名字，__PRETTY_FUNCTION__ 保存带语言特色的名字。在 C 函数中，这两个名字是相同的，在 C++ 函数中，__PRETTY_FUNCTION__ 包括函数返回类型等额外信息，Linux 内核只使用了 __FUNCTION__。</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">fs</span><span
class="hl-code">/</span><span
class="hl-identifier">ext2</span><span
class="hl-code">/</span><span
class="hl-identifier">super</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">98</span><span
class="hl-code">: </span><span
class="hl-types">void</span><span
class="hl-code"> </span><span
class="hl-identifier">ext2_update_dynamic_rev</span><span
class="hl-brackets">(</span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">super_block</span><span
class="hl-code"> *</span><span
class="hl-identifier">sb</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/></span><span
class="hl-number">99</span><span
class="hl-code">: </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">100</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-types">struct</span><span
class="hl-code"> </span><span
class="hl-identifier">ext2_super_block</span><span
class="hl-code"> *</span><span
class="hl-identifier">es</span><span
class="hl-code"> = </span><span
class="hl-identifier">EXT2_SB</span><span
class="hl-brackets">(</span><span
class="hl-identifier">sb</span><span
class="hl-brackets">)</span><span
class="hl-code">-&amp;</span><span
class="hl-identifier">gt</span><span
class="hl-code">;</span><span
class="hl-identifier">s_es</span><span
class="hl-code">;<br
/></span><span
class="hl-number">101</span><span
class="hl-code">:<br
/></span><span
class="hl-number">102</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">if</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-identifier">le32_to_cpu</span><span
class="hl-brackets">(</span><span
class="hl-identifier">es</span><span
class="hl-code">-&amp;</span><span
class="hl-identifier">gt</span><span
class="hl-code">;</span><span
class="hl-identifier">s_rev_level</span><span
class="hl-brackets">)</span><span
class="hl-code"> &amp;</span><span
class="hl-identifier">gt</span><span
class="hl-code">; </span><span
class="hl-identifier">EXT2_GOOD_OLD_REV</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/></span><span
class="hl-number">103</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">return</span><span
class="hl-code">;<br
/></span><span
class="hl-number">104</span><span
class="hl-code">:<br
/></span><span
class="hl-number">105</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">ext2_warning</span><span
class="hl-brackets">(</span><span
class="hl-identifier">sb</span><span
class="hl-code">, </span><span
class="hl-identifier">__FUNCTION__</span><span
class="hl-code">,<br
/></span><span
class="hl-number">106</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">updating to rev %d because of new feature flag, </span><span
class="hl-quotes">&quot;</span><span
class="hl-code"><br
/></span><span
class="hl-number">107</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">running e2fsck is recommended</span><span
class="hl-quotes">&quot;</span><span
class="hl-code">,<br
/></span><span
class="hl-number">108</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">EXT2_DYNAMIC_REV</span><span
class="hl-brackets">)</span><span
class="hl-code">;</span></div></div></div><p>这里 __FUNCTION__ 将被替换为字符串 &#8220;ext2_update_dynamic_rev&#8221;。虽然__FUNCTION__ 看起来类似于标准 C 中的 __FILE__，但实际上 __FUNCTION__是被编译器替换的，不象 __FILE__ 被预处理器替换。</p><h3>内建函数</h3><p>GNU C 提供了大量的内建函数，其中很多是标准 C 库函数的内建版本，例如memcpy，它们与对应的 C 库函数功能相同，本文不讨论这类函数，其他内建函数的名字通常以 __builtin 开始。</p><h4>__builtin_return_address (LEVEL)</h4><p>内建函数 __builtin_return_address 返回当前函数或其调用者的返回地址，参数LEVEL 指定在栈上搜索框架的个数，0 表示当前函数的返回地址，1 表示当前函数的调用者的返回地址，依此类推。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">kernel</span><span
class="hl-code">/</span><span
class="hl-identifier">sched</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">437</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-identifier">KERN_ERR</span><span
class="hl-code"> </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">schedule_timeout: wrong timeout </span><span
class="hl-quotes">&quot;</span><span
class="hl-code"><br
/></span><span
class="hl-number">438</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-quotes">&quot;</span><span
class="hl-string">value %lx from %pn</span><span
class="hl-quotes">&quot;</span><span
class="hl-code">, </span><span
class="hl-identifier">timeout</span><span
class="hl-code">,<br
/></span><span
class="hl-number">439</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span
class="hl-identifier">__builtin_return_address</span><span
class="hl-brackets">(</span><span
class="hl-number">0</span><span
class="hl-brackets">))</span><span
class="hl-code">;</span></div></div></div><h4>__builtin_constant_p(EXP)</h4><p>内建函数 __builtin_constant_p 用于判断一个值是否为编译时常数，如果参数 EXP 的值是常数，函数返回 1，否则返回 0。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-reserved">asm</span><span
class="hl-code">-</span><span
class="hl-identifier">i386</span><span
class="hl-code">/</span><span
class="hl-identifier">bitops</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">249</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">test_bit</span><span
class="hl-brackets">(</span><span
class="hl-identifier">nr</span><span
class="hl-code">,</span><span
class="hl-identifier">addr</span><span
class="hl-brackets">)</span><span
class="hl-code"> <br
/></span><span
class="hl-number">250</span><span
class="hl-code">: </span><span
class="hl-brackets">(</span><span
class="hl-identifier">__builtin_constant_p</span><span
class="hl-brackets">(</span><span
class="hl-identifier">nr</span><span
class="hl-brackets">)</span><span
class="hl-code"> ? <br
/></span><span
class="hl-number">251</span><span
class="hl-code">:&nbsp; </span><span
class="hl-identifier">constant_test_bit</span><span
class="hl-brackets">((</span><span
class="hl-identifier">nr</span><span
class="hl-brackets">)</span><span
class="hl-code">,</span><span
class="hl-brackets">(</span><span
class="hl-identifier">addr</span><span
class="hl-brackets">))</span><span
class="hl-code"> : <br
/></span><span
class="hl-number">252</span><span
class="hl-code">:&nbsp; </span><span
class="hl-identifier">variable_test_bit</span><span
class="hl-brackets">((</span><span
class="hl-identifier">nr</span><span
class="hl-brackets">)</span><span
class="hl-code">,</span><span
class="hl-brackets">(</span><span
class="hl-identifier">addr</span><span
class="hl-brackets">)))</span></div></div></div><p>很多计算或操作在参数为常数时有更优化的实现，在 GNU C 中用上面的方法可以根据参数是否为常数，只编译常数版本或非常数版本，这样既不失通用性，又能在参数是常数时编译出最优化的代码。</p><h4>__builtin_expect(EXP, C)</h4><p>内建函数 __builtin_expect 用于为编译器提供分支预测信息，其返回值是整数表达式 EXP 的值，C 的值必须是编译时常数。例如：</p><div
class="hl-wrapper"><div
class="hl-surround"><div
class="hl-main"><span
class="hl-code">++++ </span><span
class="hl-identifier">include</span><span
class="hl-code">/</span><span
class="hl-identifier">linux</span><span
class="hl-code">/</span><span
class="hl-identifier">compiler</span><span
class="hl-code">.</span><span
class="hl-identifier">h</span><span
class="hl-code"><br
/></span><span
class="hl-number">13</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">likely</span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">&nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__builtin_expect</span><span
class="hl-brackets">((</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">,</span><span
class="hl-number">1</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/></span><span
class="hl-number">14</span><span
class="hl-code">: #</span><span
class="hl-identifier">define</span><span
class="hl-code"> </span><span
class="hl-identifier">unlikely</span><span
class="hl-brackets">(</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">&nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">__builtin_expect</span><span
class="hl-brackets">((</span><span
class="hl-identifier">x</span><span
class="hl-brackets">)</span><span
class="hl-code">,</span><span
class="hl-number">0</span><span
class="hl-brackets">)</span><span
class="hl-code"><br
/>++++ </span><span
class="hl-identifier">kernel</span><span
class="hl-code">/</span><span
class="hl-identifier">sched</span><span
class="hl-code">.</span><span
class="hl-identifier">c</span><span
class="hl-code"><br
/></span><span
class="hl-number">564</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-reserved">if</span><span
class="hl-code"> </span><span
class="hl-brackets">(</span><span
class="hl-identifier">unlikely</span><span
class="hl-brackets">(</span><span
class="hl-identifier">in_interrupt</span><span
class="hl-brackets">()))</span><span
class="hl-code"> </span><span
class="hl-brackets">{</span><span
class="hl-code"><br
/></span><span
class="hl-number">565</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">printk</span><span
class="hl-brackets">(</span><span
class="hl-quotes">&quot;</span><span
class="hl-string">Scheduling in interruptn</span><span
class="hl-quotes">&quot;</span><span
class="hl-brackets">)</span><span
class="hl-code">;<br
/></span><span
class="hl-number">566</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-identifier">BUG</span><span
class="hl-brackets">()</span><span
class="hl-code">;<br
/></span><span
class="hl-number">567</span><span
class="hl-code">:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span
class="hl-brackets">}</span></div></div></div><p>这个内建函数的语义是 EXP 的预期值是 C，编译器可以根据这个信息适当地重排语句块的顺序，使程序在预期的情况下有更高的执行效率。上面的例子表示处于中断上下文是很少发生的，第 565-566 行的目标码可能会放在较远的位置，以保证经常执行的目标码更紧凑。</p> ]]></content:encoded> <wfw:commentRss>http://gccfeli.cn/2008/07/linux-gnu-c-extension.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>我的vimrc</title><link>http://gccfeli.cn/2008/05/my-vimrc.html</link> <comments>http://gccfeli.cn/2008/05/my-vimrc.html#comments</comments> <pubDate>Thu, 22 May 2008 04:10:57 +0000</pubDate> <dc:creator>Felicia</dc:creator> <category><![CDATA[Linux]]></category> <category><![CDATA[GVIM]]></category> <category><![CDATA[vimrc]]></category><guid
isPermaLink="false">http://www.gccfeli.cn/archives/155.html</guid> <description><![CDATA[<p>最近改的vimrc，记录在这里备用<br
/></p><div
class="hl-wrapper"> <span
class="readmore"><a
href="http://gccfeli.cn/2008/05/my-vimrc.html" title="我的vimrc">阅读全文（2549字）</a></span>]]></description> <content:encoded><![CDATA[<p>最近改的vimrc，记录在这里备用<br
/> <span
id="more-155"></span></p><div
class="hl-wrapper"><div
class="hl-title">&#19979;&#36733;: <a
href="http://gccfeli.cn/wp-content/plugins/coolcode/coolcode.php?p=155&amp;download=vimrc">vimrc</a></div><div
class="hl-surround"><div
class="hl-main">&quot; disable VI compatible<br
/>set nocompatible<br
/><br
/>&quot; set tab and indent<br
/>set tabstop=4<br
/>set softtabstop=4<br
/>set shiftwidth=4<br
/>set expandtab<br
/>set cindent<br
/>set cino=g0<br
/>set comments=s1:/*,mb:*,ex:*/<br
/><br
/>&quot; set GUI<br
/>color desert<br
/>syntax on<br
/>set mouse=a<br
/>set hlsearch<br
/>set wildmenu<br
/>set cursorline<br
/>set number<br
/>set scrolloff=5<br
/>set sidescrolloff=10<br
/>set nowrap<br
/>set ignorecase<br
/>set gfn=Courier\ 10\ Pitch\ 12<br
/><br
/>&quot; disable menus<br
/>set go=<br
/><br
/>&quot; disable startup message<br
/>set shortmess+=I<br
/><br
/>&quot; set<br
/>set magic<br
/>set timeoutlen=350<br
/><br
/>&quot; status line<br
/>set laststatus=2<br
/>set statusline=\ %F%m%r%h\ %w\ \ %r%{getcwd()}%h\ \ \ Line:\ %l/%L:%c<br
/><br
/>&quot; set window position and size<br
/>winpos 120 100<br
/>set lines=35<br
/>set columns=100<br
/><br
/>set backspace=indent,eol,start<br
/>set nobackup&nbsp; &nbsp; &quot; do not keep a backup file, use versions instead<br
/>set history=50&nbsp; &nbsp; &quot; keep 50 lines of command line history<br
/>set ruler&nbsp; &nbsp; &quot; show the cursor position all the time<br
/>set showcmd&nbsp; &nbsp; &quot; display incomplete commands<br
/>set incsearch&nbsp; &nbsp; &quot; do incremental searching<br
/>set encoding=utf-8<br
/>set fileencodings=utf-8,gb2312,gb18030,gbk,ucs-bom,cp936,latin1 <br
/>set termencoding=utf-8<br
/>set printoptions=syntax:n,number:y,portrait:y<br
/><br
/>set autoread<br
/>set helplang=cn<br
/><br
/>set ww=&lt;,&gt;,[,]<br
/><br
/><br
/>&quot; key maps<br
/><br
/>inoremap &lt;C-D&gt; &lt;C-O&gt;dd<br
/>inoremap &lt;CR&gt; &lt;CR&gt;&lt;left&gt;&lt;right&gt;<br
/>map o o&lt;left&gt;&lt;right&gt;<br
/>map O O&lt;left&gt;&lt;right&gt;<br
/>inoremap &lt;c-]&gt; {&lt;cr&gt;}&lt;c-o&gt;O&lt;left&gt;&lt;right&gt;<br
/>noremap &lt;F6&gt; =a{<br
/><br
/>let mapleader=&quot;,&quot;<br
/><br
/>&quot; for select, cut, paste<br
/>map &lt;leader&gt;a ggVG<br
/>map &lt;leader&gt;c &quot;+c<br
/>map &lt;leader&gt;y &quot;+y<br
/>map &lt;leader&gt;p &quot;+p<br
/><br
/>&quot; for tabs<br
/>map &lt;C-T&gt; :tabnew&lt;CR&gt;<br
/>imap &lt;C-T&gt; &lt;Esc&gt;&lt;C-T&gt;<br
/>map &lt;C-F4&gt; :close&lt;cr&gt;<br
/>imap &lt;C-F4&gt; &lt;Esc&gt;&lt;C-F4&gt;<br
/>map &lt;C-P&gt; :tabp&lt;cr&gt;<br
/>imap &lt;C-P&gt; &lt;Esc&gt;&lt;C-P&gt;<br
/>map &lt;C-N&gt; :tabn&lt;cr&gt;<br
/>imap &lt;C-N&gt; &lt;Esc&gt;&lt;C-N&gt;<br
/><br
/><br
/>&quot; ,w for save<br
/>nmap &lt;leader&gt;w :w!&lt;cr&gt;<br
/>&quot; ,q for quit<br
/>nmap &lt;leader&gt;q :q&lt;cr&gt;<br
/><br
/>&quot; F3 to format code<br
/>&quot;if &amp;filetype == 'cpp' <br
/>map &lt;silent&gt;&lt;F3&gt; :w&lt;cr&gt;:!astyle --style=kr %&lt;cr&gt;:n %&lt;cr&gt;<br
/>imap &lt;silent&gt;&lt;F3&gt; &lt;Esc&gt;&lt;F3&gt;<br
/>&quot;endif<br
/><br
/>&quot; F5 to insert template<br
/>map &lt;F5&gt; &lt;Esc&gt;ggdG:call Template()&lt;cr&gt;24Go<br
/>imap &lt;F5&gt; &lt;Esc&gt;&lt;F5&gt;<br
/>func Template()<br
/>let l=0<br
/>let l=l+1 | call setline(l, &quot;\/**&quot;)<br
/>let l=l+1 | call setline(l, &quot; * File Name: &quot;.expand(&quot;%&quot;)) <br
/>let l=l+1 | call setline(l, &quot; * Created Time:&nbsp; &quot;.strftime(&quot;%c&quot;)) <br
/>let l=l+1 | call setline(l, &quot; * Author: Felicia&quot;)<br
/>let l=l+1 | call setline(l, &quot; * Description: &quot;)<br
/>let l=l+1 | call setline(l, &quot; */&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;cstdio&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;cstring&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;cmath&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;cstdlib&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;algorithm&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;vector&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;set&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;map&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;string&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#include &lt;climits&gt;&quot;)<br
/>let l=l+1 | call setline(l, &quot;using namespace std;&quot;)<br
/>let l=l+1 | call setline(l, &quot;#define NEXT(v, n) (((v) == (n))? 0 : (v))&quot;)<br
/>let l=l+1 | call setline(l, &quot;#define SZ(x) ((int) x.size())&quot;)<br
/>let l=l+1 | call setline(l, &quot;typedef long long int64;&quot;)<br
/>let l=l+1 | call setline(l, &quot;template &lt;class T&gt; void get_max(T&amp; a, const T &amp;b) {b &gt; a? a = b:1;}&quot;)<br
/>let l=l+1 | call setline(l, &quot;template &lt;class T&gt; void get_min(T&amp; a, const T &amp;b) {b &lt; a? a = b:1;}&quot;)<br
/>let l=l+1 | call setline(l, &quot;&quot;)<br
/>let l=l+1 | call setline(l, &quot;int main() {&quot;)<br
/>let l=l+1 | call setline(l, &quot;&nbsp; &nbsp; return 0;&quot;)<br
/>let l=l+1 | call setline(l, &quot;}&quot;)<br
/>let l=l+1 | call setline(l, &quot;&quot;) <br
/>endfunc<br
/><br
/>cd $HOME/workspace<br
/>autocmd BufEnter * lcd %:p:h<br
/><br
/>map &lt;F9&gt; :call CR()&lt;CR&gt;&lt;space&gt;<br
/>func CR()<br
/>&nbsp;&nbsp; &nbsp;exec &quot;update&quot;<br
/>&nbsp;&nbsp; &nbsp;exec &quot;!gnome-terminal --geometry 100x30+120+120 -e \&quot;.run.sh %&lt; %&lt;.in\&quot; &quot;<br
/>endfunc<br
/><br
/>map &lt;F10&gt; :call CRm()&lt;CR&gt;&lt;space&gt;<br
/>func CRm()<br
/>&nbsp;&nbsp; &nbsp;exec &quot;update&quot;<br
/>&nbsp;&nbsp; &nbsp;exec &quot;!gnome-terminal --geometry 100x30+120+120 -e \&quot;.run.sh %&lt;\&quot; &quot;<br
/>endfunc<br
/><br
/>map&lt;F4&gt; :call SetComment()&lt;cr&gt;<br
/>func SetComment()<br
/>&nbsp;&nbsp; &nbsp;if getline('.')[0] == '/'<br
/>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;normal ^xx<br
/>&nbsp;&nbsp; &nbsp;else<br
/>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;normal 0i//<br
/>&nbsp;&nbsp; &nbsp;endif<br
/>endfunc</div></div></div> ]]></content:encoded> <wfw:commentRss>http://gccfeli.cn/2008/05/my-vimrc.html/feed</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Ubuntu中将GVIM加入快捷方式</title><link>http://gccfeli.cn/2008/05/ubuntu-gvim-shortcut.html</link> <comments>http://gccfeli.cn/2008/05/ubuntu-gvim-shortcut.html#comments</comments> <pubDate>Thu, 22 May 2008 04:08:42 +0000</pubDate> <dc:creator>Felicia</dc:creator> <category><![CDATA[Linux]]></category> <category><![CDATA[GVIM]]></category> <category><![CDATA[Ubuntu]]></category><guid
isPermaLink="false">http://www.gccfeli.cn/archives/154.html</guid> <description><![CDATA[<p>将下面文字存成gvim.desktop 放在 /usr/share/applications下就可了。<br
/></p><div
class="hl-wrapper"> <span
class="readmore"><a
href="http://gccfeli.cn/2008/05/ubuntu-gvim-shortcut.html" title="Ubuntu中将GVIM加入快捷方式">阅读全文（255字）</a></span>]]></description> <content:encoded><![CDATA[<p>将下面文字存成gvim.desktop 放在 /usr/share/applications下就可了。<br
/> <span
id="more-154"></span></p><div
class="hl-wrapper"><div
class="hl-title">&#19979;&#36733;: <a
href="http://gccfeli.cn/wp-content/plugins/coolcode/coolcode.php?p=154&amp;download=gvim.desktop">gvim.desktop</a></div><div
class="hl-surround"><div
class="hl-main">[Desktop Entry]<br
/>Name = gVim<br
/>Comment = 最好用的文本编辑器<br
/>Exec = /usr/bin/gvim<br
/>Icon = /usr/share/pixmaps/vim.svg<br
/>Terminal = false<br
/>X-MultipleArgs = false<br
/>Type = Application<br
/>Categories = Application;Development;<br
/>Encoding = UTF-8<br
/>StartupNotify = true</div></div></div> ]]></content:encoded> <wfw:commentRss>http://gccfeli.cn/2008/05/ubuntu-gvim-shortcut.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (enhanced) (user agent is rejected)
Database Caching 11/15 queries in 0.005 seconds using disk

Served from: gccfeli.cn @ 2012-05-23 02:33:32 -->
