【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 = "world";
	char dst[7] = "hello";
	strncat(dst, src, 5);
	printf("%s", dst);

	return 0;
}

因为dst容量(7)不够装下helloworld(11),因此strncat会侵占几个dst后面的字节,但是在侵占完后,strncat还是会加上一个NUL字节。因此既有不安全的一面(侵占后续字节)也有安全的一面(自动加NUL字节)

2.在src的长度不够len时,它不会用NUL字节继续填充dst

*************************以下是一些相关的辨析

#include <string.h>
#include <stdio.h>

int main()
{

	char *src = "world";
	printf("length of src is %d\n", sizeof(src));
	printf("length of src is %d\n", strlen(src));

	char dst[7] = "hello";
	int mat[100];
	strncat(dst, src, 9);
	printf("%s\n", dst);

	printf("length of dst is %d\n", sizeof(dst));
	printf("length of src is %d\n", sizeof(src));
	printf("length of src is %d\n", strlen(src));
	printf("length of mat is %d\n", sizeof(mat));

	return 0;
}

运行结果为

这说明了几点:

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 = "hello";
	printf("length of src is %d\n", sizeof(src));

	// 2
	printf("length of 'hello' is %d\n", sizeof("hello"));

	// 3
	char haha[] = "hello";
	printf("length of haha is %d\n", sizeof(haha));

	return 0;
}

运行结果为

这说明了以下几点:

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‘

时间: 2024-08-01 21:31:05

【C】字符串,字符和字节(C与指针第9章)的相关文章

C和指针 (pointers on C)——第九章:字符串、字符和字节(上)

第九章字符串.字符和字节 这一块在初学的时候很容易被大家忽视,但字符串作为一种重要的数据类型,没有在C中显式的说明.这样看起来C++定义了string的数据类型实在是带来了不少福音. 如果想用C玩OJ或者数据结构与算法的话,这一章需要仔细阅读,因为这是你仅有能用到的字符串处理的标准库. 总结: C的字符串标准库使用需要声明"string.h". strlen用于计算一个字符串的长度,它的返回值是一个无符号的整数.后面会说可能存在的问题. strcpy函数把一个字符串从一个位置赋值到另一

c# 判断字符是否是全角, 获取字符串的字节数 , 获取字符串指定长度字节数的字符串

1 Encoding.Default.GetByteCount(checkString);  =2 全角 =1 半角 /// <summary> /// 获取字符串的字节长度 /// </summary> /// <param name="str"></param> /// <returns></returns> public static int GetStringByteLength(this string s

字符串、字符、字节以及bit位小结与疑问

字符串是由一个个字符组成的,每个字符又有一个或多个字节来表示,每个字节又由8个bit位来表示 在C#里 字符串通常由string来声明,字符由char来声明,字节由byte来表示,位由bit来表示,具体分析见下面的测试代码分析: 完整测试代码: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Text;

【转载】字符,字节和编码

转自:http://www.regexlab.com/zh/encoding.htm 引言 "字符与编码"是一个被经常讨论的话题.即使这样,时常出现的乱码仍然困扰着大家.虽然我们有很多的办法可以用来消除乱码,但我们并不一定理解这些办法的内在原理.而有的乱码产生的原因,实际上由于底层代码本身有问题所导致的.因此,不仅是初学者会对字符编码感到模糊,有的底层开发人员同样对字符编码缺乏准确的理解.     1. 编码问题的由来,相关概念的理解 1.1 字符与编码的发展 从计算机对多国语言的支持

字符与字节

字节(Byte):字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位.字节是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制,它是一个8位的二进制数,是一个很具体的存储空间. 字符:人们使用的记号,抽象意义上的一个符号. '1', '中', 'a', '$', '¥', …… 我们在记事本等一些文本工具中 写的都是字符,没有谁会去写字节(可以写字节,但是要用具特殊的编辑器),但是其实,我们的写的是字符,但磁盘上真实存储的是字节. Java 流在处理上分为字符流

字符,字节和编码

摘要:本文介绍了字符与编码的发展过程,相关概念的正确理解.举例说明了一些实际应用中,编码的实现方法.然后,本文讲述了通常对字符与编码的几种误解,由于这些误解而导致乱码产生的原因,以及消除乱码的办法.本文的内容涵盖了“中文问题”,“乱码问题”. 掌握编码问题的关键是正确地理解相关概念,编码所涉及的技术其实是很简单的.因此,阅读本文时需要慢读多想,多思考. 引言 “字符与编码”是一个被经常讨论的话题.即使这样,时常出现的乱码仍然困扰着大家.虽然我们有很多的办法可以用来消除乱码,但我们并不一定理解这些

java中的字符与字节

经常听大家谈论"java使用的是Unicode编码",真不知道他们是真知道,还人云亦云 ! 首先说一下,java中class文件中使用的是utf-8编码,而在jvm运行时使用的是utf-16(如char). 一.字节的形式写.读取文件 // 以字节流的形式写出 FileOutputStream out = new FileOutputStream("text.txt"); out.write("IamChinese".getBytes("

字符、字节和编码

摘要:介绍了字符与编码的发展过程,相关概念.举例Java实际应用中,编码的实现方法.最后,讲述了通常对字符与编码的几种误解,由于这些误解而导致乱码产生的原因,以及消除乱码的方法. 1.编码问题的由来及相关概念 1.1字符与编码的发展 从计算机对多国语言的支持角度看,大致可以分为三个阶段:   系统内码 说明 系统 阶段一 ASCII 计算机刚开始只支持英语,其它语言不能够在计算机上存储和显示 英文DOS 阶段二 ANSI编码(本地化) 为使计算机支持更多语言,通常使用0x80~0xFF范围的2个

获取某个字符串的所有字节数

<script type="text/javascript">        function getBytes(str){            if(!arguments.length || !str)                return null;            if(str.length == '')                return 0;            var len = str.length;            var by