一、memset()函数介绍
函数原型 void *memset(void *str, int c, size_t n)
解释:复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
作用:是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
头文件:C中#include<string.h>,C++中#include <cstring>
代码如下:
//fill block of memory 填充内存块
//fill block of memory 填充内存块
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "almost every programmer should know memset!";
int a[1024];
double d;
memset(&d, 0, sizeof(d));
memset(a, 100, sizeof(a));
memset(str, '-', 6); //将str前6个设置为 - void * 类型都可以接收
puts(str);
return 0;
}
通过调试看到数组中的元素的值都为1684300900,而明明给它的是100,这是为什么呢?
用于初始化,但是需要注意的是memset赋值的时候是按字节赋值,是将参数化成二进制之后填入一个字节。就比如前面的例子中,想要通过memset(a,100,sizeof (a))给int类型的数组赋值,你给第一个字节的是一百,转成二进制就是0110 0100,而int有四个字节,也就是说,一个int被赋值为
0110 0100,0110 0100,0110 0100,0110 0100,对应的十进制是1684300900,根本不是你想要赋的值100,这也就解释了为什么数组中的元素的值都为1684300900。
memset赋值时只能赋值为0?
答案肯定不是,比如任意字符都是可以的,初始化成0是最常用的。int类型的一般都是赋值0或-1,其他的值都不行。
结论
为地址str开始的n个字节赋值c,注意:是逐个字节赋值,str开始的n个字节中的每个字节都赋值为c。
(1) 若str指向char型地址,value可为任意字符值;s
(2) 若str指向非char型,如int型地址,要想赋值正确,value的值只能是-1或0,因为-1和0转化成二进制后每一位都是一样的,设int型占4个字节,则-1=0XFFFFFFFF, 0=0X00000000。
举例:给数组赋值-1
int A[2];
memset(A, -1, sizeof A);
memset初始化为无穷大
memset(a , 0x3f , sizeof a);
通过memset函数的介绍,上述初始化是将数组a的每个元素赋值为0x3f3f3f3f。0x3f3f3f3f 真的是个非常精巧的常量
他的十进制是 1061109567也就是109级别的,和0x7fffffff一个数量级,0x7fffffff是int类型的最大值,即231-1=2,147,483,647。
二、memcpy()函数介绍
函数原型 : void memcpy(voiddest, const void *src, size_t n);
由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
函数返回一个指向dest的指针。
1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。
2.与strcpy相比,memcpy并不是遇到’\0’就结束,而是一定会拷贝完n个字节。
3.memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;
4.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct {
char name[40];
int age;
} person, person_copy;
//offset void * 纯地址指针变量 ++ 和*dest等都不行
//由具体类型赋值给void*,非常方便不用强转 反之,必须强转
void* MemoryCopy(void* dest, const void* src, size_t num)
{
char* p =(char*)dest;
const char* q = (const char*)src;
while (num--)
{
*p++ = *q++; //中间有没有0结尾毫无关系
}
return dest;
}
int main()
{
char myname[30];
strcpy(myname,"Pierre de Fermat");//strcpy特点是自动到达0结尾结束
/* using memcpy to copy string: */
MemoryCopy(person.name, myname, strlen(myname) + 1);
person.age = 46;
/* using memcpy to copy structure: */
memcpy(&person_copy, &person, sizeof(person));
printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
return 0;
}
三、memcmp()函数介绍
函数原型: int memcmp (const void *a1, const void *a2, size_t size)
函数memcmp用于比较字符串s1与s2的前size个字符,如果上两块字符块相同,memcmp将返回0。
函数原型:int strcmp (const char *s1, const char *s2)
这个函数用来比较s1和s2字符串,这个函数将返回一个值,它的符号与第一对不同的字符的比较结果相关。
如果两个字符串相等的话,strcmp将返回0。如果s1是s2的一个子串的话,s1小于s2
int strncmp (const char *s1, const char *s2, size_t size)
此函数与strcmp极为类似。不同之处是,strncmp函数是指定比较size个字符。也就是说,如果字符串s1与s2的前size个字符相同,函数返回值为0。
代码示例:
#include <stdio.h>
#include <string.h>
int MemoryCompare(const void* ptr1, const void* ptr2, size_t num)
{
const unsigned char* p = (const unsigned char*)ptr1;
const unsigned char* q = (const unsigned char*)ptr2;
while (*p == *q && num)
{
++q;
++p;
--num;
}
return *p - *q;
}
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = MemoryCompare(buffer1, buffer2, sizeof(buffer1));
if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}
总结
功能比较:
二者都可以用于字符串的比较,但是二者是有比较大的差异的
因为strcmp是按照字节(byte-wise)比较的,并且比较的过程中会检查是否出现了"\0"结束符,一旦任意一个字符串指针前进过程中遇到结束符,将终止比较。
而memcmp函数是用于比较两个内存块的内容是否相等,在用于字符串比较时通常用于测试字符串是否相等,不常进行byte-wise的字符串比较。如果要比较的对象中包含一些由于边界对齐需求而填入结构对象中的空格、联合
(union)结束的额外空格、字符串所分配的空间未使用完的部分引起的“holes”的话,最好使用memcmp来完成。这些“holes”的内容是不确定的,在执行byte-wise比较时结果也是不明确的。效率差异:
strcmp比较的字符串,而memcmp比较的是内存块,strcmp需要时刻检查是否遇到了字符串结束的 \0 字符,而memcmp则完全不用担心这个问题,所以memcmp的效率要高于strcmp