C语言中对内存进行操作的标准库函数有哪些?
有些函数可用来拷贝、比较和填写任意的内存块,它们都带有void。类型(并不指向任何具体类型的指针)的参数,可以处理指向任何类型的指针。
有两个函数(有点象strncpy()函数)可用来拷贝信息。第一个函数是memmove(),它把内存中的内容从一个地方拷贝到另一个地方,不管源区域和目标区域是否有相互覆盖的部分。为什么要提到这两个区域是否相互覆盖呢?假设缓冲区中已有部分数据,而你要把它们移到“后面”,以腾出缓冲区前面的空间。例12.6给出了一个试图进行这项工作的程序,但它做得并不正确:
例12.6一个试图移动数据,结果毁掉数据的程序
static char buf[] =
{'R','I','G','H','T','\0','-','-','-'};
int
main()
{
int i;
for (i = 0; i<6; ++i)
{
buf[i + 3] = buf[i]i
}
}
上述程序的意图是把buf从"RIGHT"改为“RIGRIGHT”,这样就可以在前面三个字节中存入其它数据。不幸的是,程序并没有真正实现这个意图。如果把for循环展开(或者通过调试程序来观察程序正在做什么),你就会发现程序实际上是在这样做:
buf[3] = buf[0];
buf[4] = buf[l];
buf[5] = buf[2];
buf[6] = buf[3];
buf[7] = buf[4];
buf[8] = buf[5];
buf[9] = buf[6];
数据的移动效果如图12.6a所示(新拷贝的数据用粗黑体表示)——该程序毁掉了它原来想移动的某些数据。
R I G H T \0 - - -
R I G R T \0 - - -
R I G R I \0 - - -
R I G R I G - - -
R I G R I G R - -
R I G R I G R I -
R I G R I G R I G
图12·6a“移动”相互覆盖的数据的错误方法
在移动或拷贝相互覆盖的数据时,有这样一个简单的原则:如果源区域和目标区域相互覆盖,并且源区域在目标区域的前面,则应该从源区域的末尾开始按逆向顺序依次移动数据,直到达到源区域的头部;如果源区域在目标区域的后面,则应该从源区域的头部开始移动数据,直到达到源区域的末尾。请看图12.6b。
R I G H T \0 - - -
R I G H T \0 - - \n
R I G H T \0 - T \0
R I G H T \O H T \0
R I G H T G H T \0
R I G H I G H T \O
R I G R I G H T \O
< < < L E F T \O
L < < L E F T \O
L E < L E F T \O
L E F L E F T \0
L E F T E F T \O
L E F T \0 F T \O
图12.6b“移动”相互覆盖的数据的正确方法
解释这些情况的目的是为了指出这样一点:memmove()函数知道上述原则,它能保证用正确的方法拷贝数据,不管数据是否相互覆盖。如果在拷贝或移动数据时你并不知道源区域和目标区域是否相互覆盖,你就应该使用memmove()函数。如果你能确定它们并没有相互覆盖,那么可以使用memcpy()函数,这样能稍快一些。
memcmp()函数与strncmp()函数基本相似,只是它在遇到NUL字符时不会结束。memcmp()函数不能用来比较结构的值。假设你有下面这样一个结构:
struct foo{
short s;
long 1;
}
并且假设你的程序将运行在一个short类型为两个字节(16位),long类型为4个字节(32位)的系统上。在32位的计算机中,许多编译程序会在s和l之间加入两个字节的“无用信息”,以使I从下一个字的边界开始。如果你的程序运行在低位优先(低位字节存放在低位地址中)的计算机上,那么上述结构展开后可能会如下所示:
struct foo byte[O] s的低位字节
struct foo byte[1] s的高位字节
struct foo byte[2] 无用信息(使l从一个long类型边界开始)
struct foo byte[3] 无用信息(使l从一个long类型边界开始)
struct foo byte[4] l的最低位字节
struct foo byte[5] l的次低位字节
struct foo byte[6] l的次高位字节
struct foo byte[7] 1的最高位字节
用memcmp()函数比较具有相同的s和l值的两个foo结构时,其结果并不一定相等,因为所加入的“无用信息”并不一定相同。
memchr()函数与strchr()函数基本相似,只不过它是在指定的一块内存空间中查找一个字符串,并且它在遇到第一个NUL字符时不会结束。
memset()函数对所有的C程序员都是很有用的,它能把某种字节拷贝到指定的内存空间中。memset()函数的一种常见的用法是把某种结构全部初始化为零字节。如果p是指向一个结构的指针,那么语句memset(p,'\0',size01 * p);
将把p所指向的对象全部改写为零(NUL或'\O')字节(那些使结构成员从字边界开始的“无用信息”也会被改写,但这样做没有关系,因为这些信息没有用,所以谁也不会在乎它们被改写成什么样子)。
有两个函数(有点象strncpy()函数)可用来拷贝信息。第一个函数是memmove(),它把内存中的内容从一个地方拷贝到另一个地方,不管源区域和目标区域是否有相互覆盖的部分。为什么要提到这两个区域是否相互覆盖呢?假设缓冲区中已有部分数据,而你要把它们移到“后面”,以腾出缓冲区前面的空间。例12.6给出了一个试图进行这项工作的程序,但它做得并不正确:
例12.6一个试图移动数据,结果毁掉数据的程序
static char buf[] =
{'R','I','G','H','T','\0','-','-','-'};
int
main()
{
int i;
for (i = 0; i<6; ++i)
{
buf[i + 3] = buf[i]i
}
}
上述程序的意图是把buf从"RIGHT"改为“RIGRIGHT”,这样就可以在前面三个字节中存入其它数据。不幸的是,程序并没有真正实现这个意图。如果把for循环展开(或者通过调试程序来观察程序正在做什么),你就会发现程序实际上是在这样做:
buf[3] = buf[0];
buf[4] = buf[l];
buf[5] = buf[2];
buf[6] = buf[3];
buf[7] = buf[4];
buf[8] = buf[5];
buf[9] = buf[6];
数据的移动效果如图12.6a所示(新拷贝的数据用粗黑体表示)——该程序毁掉了它原来想移动的某些数据。
R I G H T \0 - - -
R I G R T \0 - - -
R I G R I \0 - - -
R I G R I G - - -
R I G R I G R - -
R I G R I G R I -
R I G R I G R I G
图12·6a“移动”相互覆盖的数据的错误方法
在移动或拷贝相互覆盖的数据时,有这样一个简单的原则:如果源区域和目标区域相互覆盖,并且源区域在目标区域的前面,则应该从源区域的末尾开始按逆向顺序依次移动数据,直到达到源区域的头部;如果源区域在目标区域的后面,则应该从源区域的头部开始移动数据,直到达到源区域的末尾。请看图12.6b。
R I G H T \0 - - -
R I G H T \0 - - \n
R I G H T \0 - T \0
R I G H T \O H T \0
R I G H T G H T \0
R I G H I G H T \O
R I G R I G H T \O
< < < L E F T \O
L < < L E F T \O
L E < L E F T \O
L E F L E F T \0
L E F T E F T \O
L E F T \0 F T \O
图12.6b“移动”相互覆盖的数据的正确方法
解释这些情况的目的是为了指出这样一点:memmove()函数知道上述原则,它能保证用正确的方法拷贝数据,不管数据是否相互覆盖。如果在拷贝或移动数据时你并不知道源区域和目标区域是否相互覆盖,你就应该使用memmove()函数。如果你能确定它们并没有相互覆盖,那么可以使用memcpy()函数,这样能稍快一些。
memcmp()函数与strncmp()函数基本相似,只是它在遇到NUL字符时不会结束。memcmp()函数不能用来比较结构的值。假设你有下面这样一个结构:
struct foo{
short s;
long 1;
}
并且假设你的程序将运行在一个short类型为两个字节(16位),long类型为4个字节(32位)的系统上。在32位的计算机中,许多编译程序会在s和l之间加入两个字节的“无用信息”,以使I从下一个字的边界开始。如果你的程序运行在低位优先(低位字节存放在低位地址中)的计算机上,那么上述结构展开后可能会如下所示:
struct foo byte[O] s的低位字节
struct foo byte[1] s的高位字节
struct foo byte[2] 无用信息(使l从一个long类型边界开始)
struct foo byte[3] 无用信息(使l从一个long类型边界开始)
struct foo byte[4] l的最低位字节
struct foo byte[5] l的次低位字节
struct foo byte[6] l的次高位字节
struct foo byte[7] 1的最高位字节
用memcmp()函数比较具有相同的s和l值的两个foo结构时,其结果并不一定相等,因为所加入的“无用信息”并不一定相同。
memchr()函数与strchr()函数基本相似,只不过它是在指定的一块内存空间中查找一个字符串,并且它在遇到第一个NUL字符时不会结束。
memset()函数对所有的C程序员都是很有用的,它能把某种字节拷贝到指定的内存空间中。memset()函数的一种常见的用法是把某种结构全部初始化为零字节。如果p是指向一个结构的指针,那么语句memset(p,'\0',size01 * p);
将把p所指向的对象全部改写为零(NUL或'\O')字节(那些使结构成员从字边界开始的“无用信息”也会被改写,但这样做没有关系,因为这些信息没有用,所以谁也不会在乎它们被改写成什么样子)。