C 语言字符串字面量简介

目录汇总:C 语言零基础入门教程

字面串(string literal)是用一对双引号括起来的字符序列:

1
"When you come to a fork in the road, take it."

我们是在 C 语言零基础入门教程 第 2 部分中首次遇到字面串的。字面串常常作为格式串出现在 printf 函数和 scanf 函数的调用中。在标准中,字面串和字符串是彼此紧密相关但又不同的。字面串是源文件的组成部分,是程序中的一串用引号围起来的文本,仅仅是一个字面意义上的字符串,所以叫字面串。字面串经程序编译后生成字符串,而字符串是指位于系统存储器里的、以空字符终止的字符序列。

一、字面串中的转义序列

字面串可以像字符常量一样包含转义序列(C 语言字符类型简介)。我们在 printf 函数和 scanf 函数的格式串中已经使用过转义字符。例如,字符串

1
"Candy\nIs dandy\nBut liquor\nIs quicker.\n  --Ogden Nash\n"

中每一个字符 \n 都会导致光标移到下一行:

1
2
3
4
5
Candy
Is dandy
But liquor
Is quicker.
  --Ogden Nash

虽然字面串中的八进制数和十六进制数的转义序列也是合法的,但是它们不像字符转义序列那样常见。

注意

请在字面串中小心使用八进制数和十六进制数的转义序列。八进制数的转义序列在 3 个数字之后结束,或者在第一个非八进制数字符处结束。例如,字符串 "\1234" 包含两个字符(\1234),而字符串 "\189" 包含 3 个字符(\189)。而十六进制数的转义序列则不限于 3 个数字,而是直到第一个非十六进制数字符截止。思考一下,如果字符串包含转义序列 \xfc,那么会出现什么情况。\xfc 代表 Latin1 字符集中的字符 ü,Latin1 是 ASCII 的常见扩展。字符串 "Z\xfcrich"(“Zürich”)有 6 个字符(Z\xfcrich), 但是字符串 "\xfcber"(不是“über”)只有两个字符(\xfcber)。大部分编译器会拒绝接收后面那种字符串,因为十六进制数的转义序列范围通常限制在 \x0~\xff

二、延续字面串

如果发现字面串太长而无法放置在单独一行以内,只要把第一行用字符 \ 结尾,那么 C 语言就允许在下一行延续字面串。除了(看不到的)末尾的换行符,在同一行不可以有其他字符跟在 \ 后面:

1
2
printf("When you come to a fork in the road, take it.     \
--Yogi Berra");

一般说来,字符 \ 可以用来把两行或更多行的代码连接成一行[在 C 标准中这一过程称为“拼接(splicing)”]。

使用 \ 有一个缺陷:字面串必须从下一行的起始位置继续。因此,这就破坏了程序的缩进结构。根据下面的规则,处理长字面串有一种更好的方法:当两条或更多条字面串相邻时(仅用空白字符分割),编译器会把它们合并成一条字符串。这条规则允许把字符串分割放在两行或者更多行中:

1
2
printf("When you come to a fork in the road, take it. "
       "--Yogi Berra");

三、如何存储字面串

我们经常在 printf 函数调用和 scanf 函数调用中用到字面串。但是,当调用 printf 函数并且用字面串作为参数时,究竟传递了什么呢?为了回答这个问题,需要明白字面串是如何存储的。

就本质而言,C 语言把字面串作为字符数组来处理。当 C 语言编译器在程序中遇到长度为 n 的字面串时,它会为字面串分配长度为 n+1 的内存空间。这块内存空间将用来存储字面串中的字符,以及一个用来标志字符串末尾的额外字符(空字符)。空字符是一个所有位都为 0 的字节,因此用转义序列 \0 来表示。

注意

不要混淆空字符('\0')和零字符('0')。空字符的码值为 0,而零字符则有不同的码值(ASCII 中为 48)。

例如,字面串 "abc" 是作为有 4 个字符的数组来存储的(abc\0):

字面串

字面串可以为空。字符串 "" 作为单独一个空字符来存储:

字面串

既然字面串是作为数组来存储的,那么编译器会把它看作 char * 类型的指针。例如,printf 函数和 scanf 函数都接收 char * 类型的值作为它们的第一个参数。思考下面的例子:

1
printf("abc");

当调用 printf 函数时,会传递 "abc" 的地址(即指向存储字母 a 的内存单元的指针)。

四、字面串的操作

通常情况下可以在任何 C 语言允许使用 char * 指针的地方使用字面串。例如,字面串可以出现在赋值运算符的右边:

1
2
3
char *p;

p = "abc";

这个赋值操作不是复制 "abc" 中的字符,而是使 p 指向字符串的第一个字符。

C 语言允许对指针取下标,因此可以对字面串取下标:

1
2
3
char ch;

ch = "abc"[1];

ch 的新值将是字母 b。其他可能的下标是 0(这将选择字母 a)、2(字母 c)和 3(空字符)。字面串的这种特性并不常用,但有时也比较方便。思考下面的函数,这个函数把 0~15 的数转换成等价的十六进制的字符形式:

1
2
3
4
char digit_to_hex_char(int digit)
{
  return "0123456789ABCDEF"[digit];
}

注意

试图改变字面串会导致未定义的行为:

1
2
3
char *p = "abc";

*p = 'd';   /*** WRONG ***/

改变字面串可能会导致程序崩溃或运行不稳定。

五、字面串与字符常量

只包含一个字符的字面串不同于字符常量。字面串 "a" 是用指针来表示的,这个指针指向存放字符 "a"(后面紧跟空字符)的内存单元。字符常量 'a' 是用整数(字符集的数值码)来表示的。

注意

不要在需要字符串的时候使用字符(反之亦然)。函数调用

1
printf("\n");

是合法的,因为 printf 函数期望指针作为它的第一个参数。然而,下面的调用却是非法的:

1
printf('\n');    /*** WRONG ***/

请参阅

(完)

comments powered by Disqus