-
Notifications
You must be signed in to change notification settings - Fork 25
/
ch02s01.html
21 lines (19 loc) · 13 KB
/
ch02s01.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>1. 继续Hello World</title><link rel="stylesheet" href="styles.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><link rel="start" href="index.html" title="Linux C编程一站式学习" /><link rel="up" href="ch02.html" title="第 2 章 常量、变量和表达式" /><link rel="prev" href="ch02.html" title="第 2 章 常量、变量和表达式" /><link rel="next" href="ch02s02.html" title="2. 常量" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1. 继续Hello World</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch02.html">上一页</a> </td><th width="60%" align="center">第 2 章 常量、变量和表达式</th><td width="20%" align="right"> <a accesskey="n" href="ch02s02.html">下一页</a></td></tr></table><hr /></div><div class="sect1" lang="zh-cn" xml:lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2707148"></a>1. 继续Hello World</h2></div></div></div><p>在<a class="xref" href="intro.helloworld.html" title="4. 第一个程序">第 4 节 “第一个程序”</a>中,读者应该已经尝试对Hello world程序做各种改动看编译运行结果,其中有些改动会导致编译出错,有些改动会影响程序的输出,有些改动则没有任何影响,下面我们总结一下。首先,注释可以跨行,也可以穿插在程序之中,看下面的例子。</p><div class="example"><a id="id2706541"></a><p class="title"><b>例 2.1. 带更多注释的Hello World</b></p><div class="example-contents"><pre class="programlisting">#include <stdio.h>
/*
* comment1
* main: generate some simple output
*/
int main(void)
{
printf(/* comment2 */"Hello, world.\n"); /* comment3 */
return 0;
}</pre></div></div><br class="example-break" /><p>第一个注释跨了四行,头尾两行是注释的界定符(Delimiter)<a id="id2707164" class="indexterm"></a>/*和*/,中间两行开头的*号(Asterisk)<a id="id2707172" class="indexterm"></a>并没有特殊含义,只是为了看起来整齐,这不是语法规则而是大家都遵守的C代码风格(Coding Style)<a id="id2707181" class="indexterm"></a>之一,代码风格将在<a class="xref" href="ch09.html#codingstyle">第 9 章 <i>编码风格</i></a>详细介绍。</p><p>使用注释需要注意两点:</p><div class="orderedlist"><ol type="1"><li><p>注释不能嵌套(Nest)<a id="id2707207" class="indexterm"></a>使用,就是说一个注释的文字中不能再出现/*和*/了,例如<code class="literal">/* text1 /* text2 */ text3 */</code>是错误的,编译器只把<code class="literal">/* text1 /* text2 */</code>看成注释,后面的<code class="literal"> text3 */</code>无法解析,因而会报错。</p></li><li><p>有的C代码中有类似<code class="literal">// comment</code>的注释,两个/斜线(Slash)<a id="id2707243" class="indexterm"></a>表示从这里直到该行末尾的所有字符都属于注释,这种注释不能跨行,也不能穿插在一行代码中间。这是从C++借鉴的语法,在C99中被标准化。</p></li></ol></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">C语言标准</h3><p>C语言的发展历史大致上分为三个阶段:Old Style C<a id="id2707264" class="indexterm"></a>、C89<a id="id2707270" class="indexterm"></a>和C99<a id="id2707281" class="indexterm"></a>。Ken Thompson和Dennis Ritchie最初发明C语言时有很多语法和现在最常用的写法并不一样,但为了向后兼容性(Backward Compatibility)<a id="id2707292" class="indexterm"></a>,这些语法仍然在C89和C99中保留下来了,本书不详细讲Old Style C,但在必要的地方会加以说明。C89是最早的C语言规范,于1989年提出,1990年首先由ANSI(美国国家标准委员会,American National Standards Institute)<a id="id2707303" class="indexterm"></a>推出,后来被接纳为ISO国际标准(ISO/IEC 9899:1990)<a id="id2707312" class="indexterm"></a>,因而有时也称为C90<a id="id2707322" class="indexterm"></a>,最经典的C语言教材<a class="xref" href="bi01.html#bibli.kr" title="The C Programming Language">[<abbr class="abbrev">K&R</abbr>]</a>就是基于这个版本的,C89是目前最广泛采用的C语言标准,大多数编译器都完全支持C89。C99标准(ISO/IEC 9899:1999)<a id="id2707340" class="indexterm"></a>是在1999年推出的,加入了许多新特性,但目前仍没有得到广泛支持,在C99推出之后相当长的一段时间里,连<code class="literal">gcc</code>也没有完全实现C99的所有特性。C99标准详见<a class="xref" href="bi01.html#bibli.c99" title="ISO/IEC 9899: Programming Languages - C">[<abbr class="abbrev">C99</abbr>]</a>。本书讲C的语法以C99为准,但示例代码通常只使用C89语法,很少使用C99的新特性。</p><p>C标准的目的是为了精确定义C语言,而不是为了教别人怎么编程,C标准在表达上追求准确和无歧义,却十分不容易看懂,<a class="xref" href="bi01.html#bibli.standardc" title="Standard C: A Reference">[<abbr class="abbrev">Standard C</abbr>]</a>和<a class="xref" href="bi01.html#bibli.standardclib" title="The Standard C Library">[<abbr class="abbrev">Standard C Library</abbr>]</a>是对C89及其修订版本的阐释(可惜作者没有随C99更新这两本书),比C标准更容易看懂,另外,参考<a class="xref" href="bi01.html#bibli.rationale" title="Rationale for International Standard - Programming Languages - C">[<abbr class="abbrev">C99 Rationale</abbr>]</a>也有助于加深对C标准的理解。</p></div><p>像<code class="literal">"Hello, world.\n"</code>这种由双引号(Double Quote)<a id="id2707397" class="indexterm"></a>引起来的一串字符称为字符串字面值(String Literal)<a id="id2707405" class="indexterm"></a>,或者简称字符串。注意,程序的运行结果并没有双引号,<code class="literal">printf</code>打印出来的只是里面的一串字符<code class="literal">Hello, world.</code>,因此双引号是字符串字面值的界定符,夹在双引号中间的一串字符才是它的内容。注意,打印出来的结果也没有<code class="literal">\n</code>这两个字符,这是为什么呢?在<a class="xref" href="intro.naturalformal.html" title="2. 自然语言和形式语言">第 2 节 “自然语言和形式语言”</a>中提到过,C语言规定了一些转义序列(Escape Sequence)<a id="id2707438" class="indexterm"></a>,这里的<code class="literal">\n</code>并不表示它的字面意思,也就是说并不表示\和n这两个字符本身,而是合起来表示一个换行符(Line Feed)<a id="id2707454" class="indexterm"></a>。例如我们写三条打印语句:</p><pre class="programlisting">printf("Hello, world.\n");
printf("Goodbye, ");
printf("cruel world!\n");</pre><p>运行的结果是第一条语句单独打到第一行,后两条语句都打到第二行。为了节省篇幅突出重点,以后的例子通常省略<code class="literal">#include</code>和<code class="literal">int main(void) { ... }</code>这些Boilerplate,但读者在练习时需要加上这些构成一个完整的程序才能编译通过。C标准规定的转义字符有以下几种:</p><div class="table"><a id="id2707486"></a><p class="title"><b>表 2.1. C标准规定的转义字符</b></p><div class="table-contents"><table summary="C标准规定的转义字符" border="1"><colgroup><col /><col /></colgroup><tbody><tr><td>\'</td><td>单引号'(Single Quote或Apostrophe)<a id="id2707507" class="indexterm"></a></td></tr><tr><td>\"</td><td>双引号"</td></tr><tr><td>\?</td><td>问号?(Question Mark)<a id="id2707526" class="indexterm"></a></td></tr><tr><td>\\</td><td>反斜线\(Backslash)<a id="id2707538" class="indexterm"></a></td></tr><tr><td>\a</td><td>响铃(Alert或Bell)<a id="id2707551" class="indexterm"></a></td></tr><tr><td>\b</td><td>退格(Backspace)<a id="id2707562" class="indexterm"></a></td></tr><tr><td>\f</td><td>分页符(Form Feed)<a id="id2707574" class="indexterm"></a></td></tr><tr><td>\n</td><td>换行(Line Feed)</td></tr><tr><td>\r</td><td>回车(Carriage Return)<a id="id2707592" class="indexterm"></a></td></tr><tr><td>\t</td><td>水平制表符(Horizontal Tab)<a id="id2707604" class="indexterm"></a></td></tr><tr><td>\v</td><td>垂直制表符(Vertical Tab)<a id="id2707616" class="indexterm"></a></td></tr></tbody></table></div></div><br class="table-break" /><p>如果在字符串字面值中要表示单引号和问号,既可以使用转义序列<code class="literal">\'</code>和<code class="literal">\?</code>,也可以直接用字符'和?,而要表示\或"则必须使用转义序列,因为\字符表示转义而不表示它的字面含义,"表示字符串的界定符而不表示它的字面含义。可见转义序列有两个作用:一是把普通字符转义成特殊字符,例如把字母n转义成换行符;二是把特殊字符转义成普通字符,例如\和"是特殊字符,转义后取它的字面值。</p><p>C语言规定了几个控制字符,不能用键盘直接输入,因此采用\加字母的转义序列表示。<code class="literal">\a</code>是响铃字符,在字符终端下显示这个字符的效果是PC喇叭发出嘀的一声,在图形界面终端下的效果取决于终端的实现。在终端下显示<code class="literal">\b</code>和按下退格键的效果相同。<code class="literal">\f</code>是分页符,主要用于控制打印机在打印源代码时提前分页,这样可以避免一个函数跨两页打印。<code class="literal">\n</code>和<code class="literal">\r</code>分别表示Line Feed和Carriage Return,这两个词来自老式的英文打字机,Line Feed是跳到下一行(进纸,喂纸,有个喂的动作所以是feed),Carriage Return是回到本行开头(Carriage是卷着纸的轴,随着打字慢慢左移,打完一行就一下子移回最右边),如果你看过欧美的老电影应该能想起来这是什么。用老式打字机打完一行之后需要这么两个动作,<code class="literal">\r\n</code>,所以现在Windows上的文本文件用<code class="literal">\r\n</code>做行分隔符,许多应用层网络协议(如HTTP)也用<code class="literal">\r\n</code>做行分隔符,而Linux和各种UNIX上的文本文件只用<code class="literal">\n</code>做行分隔符。在终端下显示<code class="literal">\t</code>和按下Tab键的效果相同,用于在终端下定位表格的下一列,<code class="literal">\v</code>用于在终端下定位表格的下一行。<code class="literal">\v</code>比较少用,<code class="literal">\t</code>比较常用,以后将“<span class="quote">水平制表符</span>”简称为“<span class="quote">制表符</span>”或Tab。请读者用<code class="literal">printf</code>语句试试这几个控制字符的作用。</p><p>注意<code class="literal">"Goodbye, "</code>末尾的空格,字符串字面值中的空格也算一个字符,也会出现在输出结果中,而程序中别处的空格和Tab多一个少一个往往是无关紧要的,不会对编译的结果产生任何影响,例如不缩进不会影响程序的结果,<code class="literal">main</code>后面多几个空格也没影响,但是<code class="literal">int</code>和<code class="literal">main</code>之间至少要有一个空格分隔开:</p><pre class="programlisting">int main (void)
{
printf("Hello, world.\n");
return 0;
}</pre><p>不仅空格和Tab是无关紧要的,换行也是如此,我甚至可以把整个程序写成一行,但是<code class="literal">include</code>必须单独占一行:</p><pre class="programlisting">#include<stdio.h>
int main(void){printf("Hello, world.\n");return 0;}</pre><p>这样也行,但肯定不是好的代码风格,去掉缩进已经很影响可读性了,写成现在这个样子可读性更差。如果编译器说第2行有错误,也很难判断是哪个语句有错误。所以,<span class="emphasis"><em>好的代码风格要求缩进整齐,每个语句一行,适当留空行</em></span>。</p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch02.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="ch02.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="ch02s02.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">第 2 章 常量、变量和表达式 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 2. 常量</td></tr></table></div></body></html>