C++Primer 3.5.1: C-style character string
C-Style Character Strings
C-Style strings
are not a type. They are a convention for how to represent and use character strings.
C-Style strings
指的是一种指定如何表示和使用character strings
的规定。该规定要求:
character strings
存储在character array
中;null terminated
。即该character array
最后一个element为null character '\0'(ansii = 0)
。
例如,C++中的string literals
就是一个C-Style string
(从C中继承而来),也就是说,在C++中string literals
是null terminated
。注意在这里出现了几个很容易混淆的定义,我们需要通过实际例子来辨析:
'a' // a character 'a'
"hello, world"; // a string literal, has '\0'
char sa[] = {'h','e','l','l','o'}; // sa is a character array, no '\0'
char *p = "hello, world"; // p is a pointer to a string literal "hello, world", p points to the first element of this string literal
string s("hello, world"); // s is a string(library type)
首先,string literals
指的就是一个字符串字面量,其是一个常量,存储在DS
段。因为C/C++中的string literals
都遵循C-Style Strings
规定,因此C/C++中的string literals
都是存储在一个character array
中,且这个character array
的最后一个元素是'\0'
。
其次,sa
是一个charater array
数组,也就是常说的字符数组(char数组
)。数组中的每个element都是一个character
,也就是常说的字符(char
)。字符数组并不遵循C-Style strings
规则,所以其并不要求最后一个元素是'\0'
,即并不是null terminated
。但是需要注意的是,尽管sa
在进行操作时会被compiler转换为一个指向首元素的指针
,但是其是一个char * const的指针,即指针自身不能被修改,所以并不能给sa
赋值。同理,也不能再次使用string literals
给sa
赋值(注意这里如果使用string literals
给sa
进行初始化是可以的)。
类似的,p
是一个char
类型的指针,也就是常说的char *
,其指向一个string literals
常量,更准确的说是指向该hello, world
的首元素(即h
字符)。因为string literals
是一个character array
,所以可以通过这个指向首元素的指针来实现subscript
操作。但是需要注意的是,因为此时hello, world
是一个常量,所以尽管可以通过取下标获得其中某个element,但是并不能修改这个element。更多关于char*
和char[]
的区别可以查看here。
最后,就是string
类,其是library type
,相应的操作符都在类中被重载。注意,在C++11标准中,明确规定了string
也是null terminated
,即以'\0'
结尾,here。
C library string functions
因为C standard library并没有重载诸如+
,==
等操作符,所以并不能用C++中的string
类中重载这些操作符对C-Style string
进行操作。相反,C中提供了一系列functions来操作C-Style string
。例如:
Functions | Meaning |
---|---|
strlen (p) |
Returns the length of p , not couting the null |
strcmp (p1, p2) |
Compares p1 and p2 for equality. Returns 0 if p1 == p2 , a positive value if p1 > p2 , a negative value if p1 < p2 . |
strcat (p1, p2) |
Appends p2 to p1 . Returns p1 . |
strcpy (p1, p2) |
Copies p2 into p1 . Returns p1 . |
其中这些函数的实参必须是指向null terminated array
的指针。如果传入的指针不是指向null terminated array
,那么会出现undefined
的情况。例如strlen
,则会不断循环直到找到null
。
在C++中,因为string
已经重载了很多操作符,所以使用起来很方便。例如,当我们想拼接两个字符串时:
/* c++ */
string s1("hello");
string s2("world");
string largeStr = s1 + ' ' + s2;
/* c */
char s1[] = "hello";
char s2[] = "world";
char largeStr[12];
strcpy(largeStr, s1);
strcat(largeStr, " "); // can't use ' ', because " " is a string literal, can be converted to pointer
strcat(largeStr, s2);
可以看到,在C中想要实现拼接字符串非常麻烦,需要定义一个largeStr
来接收拼接好的字符串;并且还需要计算好新的字符串的长度。但是在C++中如果使用string
类的话则可以直接使用重载的+
进行操作。
Mixing library strings
and C-Style Strings
通常来说,在任何要求使用string literal
的地方,我们都可以使用null-terminated array
。但是反过来却不行,即我们不能在要求使用C-Style Strings
的地方使用library strings
。
string s("hello, world");
char *str = s; // error, can't initialize a char* from a string
const char *str = s.c_str(); // ok
但是string
类中提供了一个member function来返回一个C-Style string
。具体来说,c_str()
函数返回一个指向一个null-terminated数组首元素的指针
,其中这个数组具有与string
一样的elements。换句话说,c_str()
提供了一个方法来获得C-Style string
,这个返回的null-terminated
数组与string
中的内容一样。但是需要注意的是,c_str()
并不能保证一直有效,任何有可能改变s
的值的操作都会使这个返回的数组失效。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 gzrjzcx@qq.com
文章标题:C++Primer 3.5.1: C-style character string
文章字数:1.2k
本文作者:Alex Zou
发布时间:2019-12-09, 13:45:32
最后更新:2024-07-10, 03:02:36
原始链接:https://www.hellscript.cc/2019/12/09/subposts_cppPrimer/CPN-3-5-1-C-style-character-string/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。