-
Notifications
You must be signed in to change notification settings - Fork 25
/
ch08s04.html
3 lines (3 loc) · 6.78 KB
/
ch08s04.html
1
2
3
<?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>4. 字符串</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="ch08.html" title="第 8 章 数组" /><link rel="prev" href="ch08s03.html" title="3. 数组应用实例:直方图" /><link rel="next" href="ch08s05.html" title="5. 多维数组" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. 字符串</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch08s03.html">上一页</a> </td><th width="60%" align="center">第 8 章 数组</th><td width="20%" align="right"> <a accesskey="n" href="ch08s05.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="id2734544"></a>4. 字符串</h2></div></div></div><p>之前我一直对字符串避而不谈,不做详细解释,现在已经具备了必要的基础知识,可以深入讨论一下字符串了。字符串可以看作一个数组,它的每个元素是字符型的,例如字符串<code class="literal">"Hello, world.\n"</code>图示如下:</p><div class="figure"><a id="id2734565"></a><p class="title"><b>图 8.2. 字符串</b></p><div class="figure-contents"><div><img src="images/array.string.png" alt="字符串" /></div></div></div><br class="figure-break" /><p>注意每个字符末尾都有一个字符<code class="literal">'\0'</code>做结束符,这里的<code class="literal">\0</code>是ASCII码的八进制表示,也就是ASCII码为0的Null字符,在C语言中这种字符串也称为以零结尾的字符串(Null-terminated String)<a id="id2734595" class="indexterm"></a>。数组元素可以通过数组名加下标的方式访问,而字符串字面值也可以像数组名一样使用,可以加下标访问其中的字符:</p><pre class="programlisting">char c = "Hello, world.\n"[0];</pre><p>但是通过下标修改其中的字符却是不允许的:</p><pre class="programlisting">"Hello, world.\n"[0] = 'A';</pre><p>这行代码会产生编译错误,说字符串字面值是只读的,不允许修改。字符串字面值还有一点和数组名类似,做右值使用时自动转换成指向首元素的指针,在<a class="xref" href="ch03s03.html#func.paraarg">第 3 节 “形参和实参”</a>我们看到<code class="literal">printf</code>原型的第一个参数是指针类型,而<code class="literal">printf("hello world")</code>其实就是传一个指针参数给<code class="literal">printf</code>。</p><p>前面讲过数组可以像结构体一样初始化,如果是字符数组,也可以用一个字符串字面值来初始化:</p><pre class="programlisting">char str[10] = "Hello";</pre><p>相当于:</p><pre class="programlisting">char str[10] = { 'H', 'e', 'l', 'l', 'o', '\0' };</pre><p><code class="literal">str</code>的后四个元素没有指定,自动初始化为0,即Null字符。注意,虽然字符串字面值<code class="literal">"Hello"</code>是只读的,但用它初始化的数组<code class="literal">str</code>却是可读可写的。数组<code class="literal">str</code>中保存了一串字符,以<code class="literal">'\0'</code>结尾,也可以叫字符串。在本书中只要是以Null字符结尾的一串字符都叫字符串,不管是像<code class="literal">str</code>这样的数组,还是像<code class="literal">"Hello"</code>这样的字符串字面值。</p><p>如果用于初始化的字符串字面值比数组还长,比如:</p><pre class="programlisting">char str[10] = "Hello, world.\n";</pre><p>则数组<code class="literal">str</code>只包含字符串的前10个字符,不包含Null字符,这种情况编译器会给出警告。如果要用一个字符串字面值准确地初始化一个字符数组,最好的办法是不指定数组的长度,让编译器自己计算:</p><pre class="programlisting">char str[] = "Hello, world.\n";</pre><p>字符串字面值的长度包括Null字符在内一共15个字符,编译器会确定数组<code class="literal">str</code>的长度为15。</p><p>有一种情况需要特别注意,如果用于初始化的字符串字面值比数组刚好长出一个Null字符的长度,比如:</p><pre class="programlisting">char str[14] = "Hello, world.\n";</pre><p>则数组<code class="literal">str</code>不包含Null字符,并且编译器不会给出警告,<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><p>补充一点,<code class="literal">printf</code>函数的格式化字符串中可以用<code class="literal">%s</code>表示字符串的占位符。在学字符数组以前,我们用<code class="literal">%s</code>没什么意义,因为</p><pre class="programlisting">printf("string: %s\n", "Hello");</pre><p>还不如写成</p><pre class="programlisting">printf("string: Hello\n");</pre><p>但现在字符串可以保存在一个数组里面,用<code class="literal">%s</code>来打印就很有必要了:</p><pre class="programlisting">printf("string: %s\n", str);</pre><p><code class="literal">printf</code>会从数组<code class="literal">str</code>的开头一直打印到Null字符为止,Null字符本身是Non-printable字符,不打印。这其实是一个危险的信号:如果数组<code class="literal">str</code>中没有Null字符,那么<code class="literal">printf</code>函数就会访问数组越界,后果可能会很诡异:有时候打印出乱码,有时候看起来没错误,有时候引起程序崩溃。</p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch08s03.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="ch08.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="ch08s05.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">3. 数组应用实例:直方图 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 5. 多维数组</td></tr></table></div></body></html>