字节序列操作函数

字符串是以\0(即NUL)结尾的一串字符指针。所以一个字符串内部不可能包括任何NUL字符,但是,非字符串数据内部包含NUL的并不罕见。我们不能用字符串函数(如strcat/strcpy等)来处理这些数据,因为他们碰到NUL就会停止工作。

不过"mem"家族的函数给了我们几大帮助,它们能处理任意的字节序列,是对内存的直接操作。

memcpy

函数原型:void *memcpy(void *dest, const void *src, size_t n);

这个函数长的就和strcpy很像,就是姓不同,估计是表兄吧。作用是从src指向的地址开始,复制n个字节的数据到dest指向的地址里。其中n是size_t类型,很多同学表示不懂,其实size_t就是无符号整型。

取n的时候一定要注意,不要以为char就一定是一个字节,于是字符串有5个字母就填5.一定要用sizeof取一下你要复制的数据所占的内存大小。

与strcpy的区别在于,memcpy函数能够处理非字符串的数据,比如memcpy(value1,value2,sizeof(value2));其中value2可以是int 类型的数组,而value1可以是int 类型的指针。他们并不需要强制转换成void 类型的指针,因为任何类型指针都可以直接转换成void* 类型。

注意,当dest 和 src 指向的地址在内存里发生重叠了,会产生不可预料的后果。(于是,下面一个函数应运而生)

memmove

函数原型:void *memmove( void* dest, const void* src, size_t count );

这个函数和上一个用法一样,但它的源和目标可以重叠。就好像操作是这样:先把src保存的内容复制到一个临时的地址保存,再将这个内容从临时地址拷贝到dest中。这样即使dest和src指向的地址重叠,也能完成拷贝操作(只是效率低了)。所以,如果地址真的可能发生重叠的时候,务必就要用上memmove函数了,比如:

memmove(arr+1,arr,10*sizeof(arr[0])); //将arr数组整体向后移动一个位置

memcmp

函数原型:void* memcmp(const void* a,const void* b,size_t length);

用法与strcmp相似,从ab指向的地址开始,对无符号字符逐字节进行比较,共比较length个字节。相等返回0,a小于b返回负值,a大于b返回正值。如果a、b地址里保存的不是字符类型,就会产生不可预料的错误。

memchr

函数原型:void* memchr(const void* a,int ch,size_t length);

从a的起始位置开始查找ch第一次出现的位子,并返回一个指向该位置的指针。它共查找length个字节。如果未找到则返回NULL.

memset

函数原型:void* memset(void* a,int ch,size_t length);

这个放在最后,其实用的反而比较多,把从a开始的length个字节都初始化为ch.

大概常用的就是这些。有了这些函数,我们就扩展了许多对于数组进行操作的知识。而且我们还要注意,不要总想着自己写一个函数来替代库函数的功能。这些库函数用汇编写的效率已经是很高了,我们把它们记住,需要的时候就直接用。

C的魅力我就不多说了,这些对于系统内存操作的函数已经将她展现的淋漓尽致。

赞赏

喜欢这篇文章,扫码和我成为赞友!

评论

狒狒 回复

写的不错
不过看着还是有点头疼

落沐萧萧 回复

@狒狒:学这个经常头疼……

昵称 回复

@落沐萧萧:哈哈.

双城记 回复

这真是一个很有特色的博客啊。

captcha