字符串
1. 字符串字面量
字符串字面量是用一对双引号括起来的字符序列:
“When you come to a fork in the road , take it.”
1.1 字符串字面量中的转义序列
字符串字面量可以像字符串字面量一样包含转义序列。我们在printf函数和scanf函数的调用中。例如,字符串
"Candy\nIs dandy\nBut liquor\nIs quicker.\n --Ogden Nash\n"
中的每一个字符\n都会导致光标移到下一行:
Candy
Is dandy
But liquor
Is quicker
--Ogden Nash
虽然字符串字面量中的八进制数和十六进制的转义序列也都是合法的,但是它们不像字符转义序列那样常见。
Notice:
请在字符串字面量中小心使用八进制和十六进制数的转义序列。八进制数的转义序列在3个数字之后结束,或者在第一个非八进制数字符结束。例如,字符串”\1234“包含两个字符(\123和4),而字符串”\189“包含3个字符(\1、8和9)。而十六进制数的转义序列则不限制为3个数字,而是直到第一个非十六进制数字符截止。十六进制的转义序列通常范围限制在\x0 - \xff。
1.2 延续字符串字面量
如果发现字符串字面量太长而无法放置在单独一行内,只要把第一行用字符\结尾,那么C语言就允许在下一行延续字符串字面量。除了(看不到的)末尾的换行符,在同一行不可以有其他字符跟在\后面:
- printf("When you come to a fork in the road,take it. \
- --Yogi Berra");
一般来说,字符\可以用来把两行或更多行的代码连接成一行(在C标准中这一过程称为”拼接“)。
使用\有一个缺陷:字符串字面量必须从下一行的起始位置继续。因此,这就破坏了程序的缩进结构。根据下面的规则,处理长字符串字面量有一种更好的方法:当两条或更多条字符串字面量相邻时(仅用空白字符分割),编译器会把它们合并成一条字符串。这条规则允许把字符串分割放在两行或更多行中:
- printf("When you come to a fork in the road,take it. ” “--Yogi Berra");
1.3 如何存储字符串字面量
我们经常在printf函数调用和scanf函数调用中用到字符串字面量。但是,当调用printf函数并且用字符串字面量作为参数时,究竟传递了什么呢?为了回答这个问题,需要明白字符串字面量是如何让存储的。
从本质而言,C语言把字符串在字面量作为字符数组来处理。当C语言编译器在程序中遇到长度为n的字符串字面量时,它会为字符串字面量分配为n+1的内存空间。这块内存空间将用到来存储字符串字面量中的字符,以及一个用来标志字符串末尾的额外字符(空字符)。空字符是一个所有位都为0的字节,因此用转义序列\0来表示。
不要混淆空字符(‘ \0 ’)和(‘ 0 ’)。空字符的码值为0,而零字符则有不同的码值(ASCII中为48)。
例如,字符串字面量”abc“是作为有4个字符的数组来存储的(a、b、c和\0):
字符串字面量可以为空。字符串” “作为单独一个空字符来存储:
既然字符串字面量是作为数组来存储的,那么编译器会把它看作是char 类型的指针。例如,printf函数和scanf函数都接收char 类型的值作为它们的第一个参数。思考下面的例子:
- printf("abc");
- 当调用printf函数时,会传递”abc“的地址(即指向存储字母a的内存单元的指针)。
1.4 字符串字面量的操作
通常情况下可以在任何C语言允许使用char * 指针的地方使用字符串字面量。例如,字符串字面量可以出现赋值运算符的右边:
-
char *p;
-
p = "abc";
-
这个赋值操作不是赋值”abc“中的字符,而是使p指向字符串的第一个字符。
C语言允许对指针取下标,因此可以对字符串字面量取下标:
-
char ch;
-
ch = "abc"[1];
-
ch的新值将是字母b。其他可能的下标是0(这将选择字母a)、2(字母c)和3(空字符)。字符串字面量的这种特性并不常用,但有时也比较方便。思考下面的函数,这个函数把0~15的数将换成等价的十六进制的字符形式:
char digit_to_hex_char(int digit)
{
return "0123456789ABCDEF"[digit];
}
Notice:
试图改变字符串字面量会导致未定义的行为:
char *p = "abc";
*p = 'd'; //WRONG
改变字符串字面量可能会导致程序崩溃或运行不稳定。
1.5 字符串字面量和字符常量
只包含一个字符的字符串字面量不同于字符常量。字符串字面量“a”是用指针来表示的,这个指针指向存放字符“a”(后面紧跟空字符)的内存单元。字符常量‘a’是用整数(字符集的数码值)来表示的。
不要在需要字符串的时候使用字符(反之亦然)。函数调用
printf("\n");
是合法的,因为printf函数期望指针作为它的第一个参数。然而,下面的调用却是非法的: printf('\n');
2. 字符串变量
一些编程语言为声明字符串变量提供了专门的string类型。C语言采取了不同的方式:只要保证字符串是以空字符结尾的,任何一维的字符数组都可以用来存储字符串。这种方法很简单,但使用起来有很大难度 ,有时很难辨别是否把字符数组作为字符串来使用。如果编写自己的字符串处理函数,请千万注意要正确地处理空字符。而且,要确定字符串长度没有比逐个字符搜索空字符更快捷的方法了。
0 条评论