首页 > 代码库 > 【C】字符串,字符和字节(C与指针第9章)
【C】字符串,字符和字节(C与指针第9章)
C语言没有一种显式的数据类型是字符串的。
C语言存储字符串:字符串常量(不能修改);字符数组或动态分配的内存(可以修改)
****************************************************
9.1 字符串基础
字符串概念:字符串是以一个位模式为全0的NUL字节结尾的0个或多个字符
NUL字节是终止符,字符串的长度不包含NUL字节
头文件string.h包含了使用字符串函数所需的原型和声明(可以在linux中查看,有很多函数声明)。
****************************************************
9.2 字符串长度
size_t是一个无符号整数类型。定义与stddef.h头文件
做算术运算的时候无符号整数可能导致不可预料的结果(想想,见9.2)
****************************************************
9.3 不受限制的字符串函数
——》复制字符串 strcpy函数: char *strcpy( char *dst, char const *src);
Note:
1.复制字符串也会复制NUL字节;
2.如果dst目标字符数组空间不足以容纳需要复制的字符串,strcpy将侵占数组后面的部分内存空间(因为strcpy无法判断目标字符数组的长度,这也是”不受限制“的含义吧)
——》连接字符串 strcat函数: char *strcat( char *dst, char const *src );
Note:
1.这个函数找到dst的末尾(NUL字节吗),把src字符串的一份拷贝添加到这个位置
2.这个函数也有strcpy的特点,如果dst空间不足以容纳需要复制的字符串了,则也将侵占数组后面的部分空间
——》字符串比较 strcmp: int strcmp(char const *s1, char const *s2);
Note:
1.这个函数的结果符合“字典比较”
****************************************************
9.4 长度指定了限制的字符串函数
上面没有受限的函数是以寻找字符串结尾的NUL字节来判断长度;这里的函数指定进行复制或比较的字符数
——》strncpy函数:char *strncpy( char *dst, char const *src, size_t len );
Note:
1.把源字符串src的指定数目字符复制到目标数组dst;如果src没有len个字符,则会用NUL字节填充到dst
2.如果是strlen(src)大于len,那么只有len个字符会进行复制。!但是,它的结果将不会以NUL字节结尾。(也就是说,strncpy调用的结果可能不是一个字符串哦)
——》strncat函数:char *strncat( char *dst, char const *src, size_t len);
Note:
1.strncat在连接完后,会自动在结果后加上一个NUL(因此这还是比较安全的,不会因为没有NUL而在其他函数中出现问题),例如下程序
#include <string.h> #include <stdio.h> int main() { char *src = http://www.mamicode.com/"world";>因为dst容量(7)不够装下helloworld(11),因此strncat会侵占几个dst后面的字节,但是在侵占完后,strncat还是会加上一个NUL字节。因此既有不安全的一面(侵占后续字节)也有安全的一面(自动加NUL字节)
2.在src的长度不够len时,它不会用NUL字节继续填充dst
*************************以下是一些相关的辨析
#include <string.h> #include <stdio.h> int main() { char *src = http://www.mamicode.com/"world";>运行结果为
这说明了几点:
1.对于数组名来说,一般是作为指针,但是在sizeof(数组名)中,是求取了数组占用的“字节”数;
2.在strncat后,输出helloworld后,对dst数组求字节数却还是7. 说明数组长度是被记录下来的,不会变化了。但是往后只要用%s格式输出dst,都会输出helloworld。因为在后面都加入了‘\0‘;
3.完全不解!为什么在开始strlen(src)还有5,但是在调用了strncat之后strlen(src)就只有1了?求解答~
再看以下的程序
#include <string.h> #include <stdio.h> int main() { //1 *src = http://www.mamicode.com/"hello";>
运行结果为
这说明了以下几点:
1. 行1&2结合,我的分析是,在1中src在可重定位目标文件中是一个存在于符号表中的标识符,是一个指针变量,以常量字符串“hello”的起始地址初始化(运行时);而在2中“hello”是一个常量字符串,在运行前已经存放好,放在可重定位目标文件(编译汇编之后,链接之前产生的文件).rodata segment中(?不对耶,用objdump查看了,行1中的“hello”确实存放在rodata段中,但是sizeof(“hello”)中的“hello”没有放在rodata中,因为若删去第1行,则rodata中没有hello了,如下图是删去了第1行两句话)
2.结合2&3分析,说明字符数组包含了‘\0‘
【C】字符串,字符和字节(C与指针第9章)