1. memcpy 与 strcpy
memcpy() 函数与 strcpy() 函数(https://blog.csdn.net/gltzlike/article/details/119445386?spm=1001.2014.3001.5501)用法大致相同。memcpy() 函数将第二个变量的指定数量内存块复制到第一个变量内存块的起始位置,且需要指定复制几个内存块。mem 开头的函数都有这个特点,都需要指定操作内存块的数量。(strcpy 函数的操作仅适用于字符串,字符串自带 '\0' 结束标志,不需要指定操作内存块数量)
void TestMemcpy(){
char string1[] = "ABCDE";
char* string2 = "FGHIJ";
memcpy(string1, string2, 4); // string2 复制 4 个字节到 string1 中
printf("string1: %s\n", string1); // FGHIE
}
2. memchr 与 strchr
memchr() 函数与 strchr() 函数(https://blog.csdn.net/gltzlike/article/details/119422102?spm=1001.2014.3001.5501)类似,都是找寻一个字符。区别在于 memchr() 函数在一段内存中查找一个字符,strchr() 函数在一个字符串中查找一个字符。例如代码中 memchr() 可以去 int 类型的数组查找一个字符,虽然结果为 NULL。
void TestMemchr(){
// 从字符串中查找
char string1[] = "Hello";
char* temp = memchr(string1, 'l', 5);
printf("%s\n", temp); // llo
// 从数组中查找
int a[] = {0,1,2,3,4};
char* temp2 = memchr(a, 48, 5); // 48 对应的是ASCII码表中的 '0'
printf("%s\n", temp2); // (null)
}
3. memcmp 与 strcmp
memcmp() 函数可以和 strcmp() 函数(https://blog.csdn.net/gltzlike/article/details/115499373?spm=1001.2014.3001.5501)一样,去比较字符串的大小,但也可以去比较 int 类型的数组大小。但在比较时需注意,一个 int 4 个字节,选择的字节数会影响比较结果。
void TestMemcmp(){
// 比较字符串大小
char *left = "Hello W";
char *right = "Hello C";
printf("%d\n", memcmp(right, left, 7)); // right<left -1
printf("%d\n", memcmp(left, right, 7)); // left>right 1
printf("%d\n", memcmp(left, right, 6)); // left=right 0
// 比较数组大小
int a[] = {2,2,0,4,5};
int b[] = {2,2,3,4,5};
int result = memcmp(a, b, 8);
printf("a?b: %d\n", result); // a?b: 0
int result2 = memcmp(a, b, 9);
printf("a?b: %d\n", result2); // a?b: -1
}
如上述代码所示,a 数组和 b 数组比较前八个字节时,a==b,比较第九个字节时才能发现 a<b。原因在于 memcmp() 函数是一个字节位一个字节位进行数组元素比较的,如下图所示,数组中的第三个元素是从第八个字节位开始存储的(0为起点)。
4. memset
memset() 函数没有与之对应的 string 兄弟,它的功能是将指定数量内存块(字节)的存储值都设置为某一个值。
void TestMemset(){
char *a = malloc(5); // 请求分配 5 个字节
for (int i = 0; i < 5; ++i) {
printf("%d, ", a[i]); // -51, -51, -51, -51, -51,
}
memset(a, 0, 5); // 将 5 个字节的值设置为 0
printf("\n");
for (int i = 0; i < 5; ++i) {
printf("%d, ", a[i]); // 0, 0, 0, 0, 0,
}
free(a);
}
5. memmove
memmove() 函数与 memcpy() 函数类似,参数一致,执行结果在 msvc 和 gcc 编译器下相同。memmove() 也是将第二个变量的内存块复制到第一块内存的起始地址,唯一的不同是 memmove() 函数更适用于第一个变量和第二个变量的内存区域有重叠。
void TestMemmove(){
char str[] = "memmove can be very useful......";
memmove (str+20,str+15,11);
puts (str); // memmove can be very very useful.
char str2[] = "memmove can be very useful......";
memcpy(str2+20,str2+15,11);
puts(str2); // memmove can be very very useful.
}
图出处:http://c.biancheng.net/cpp/html/156.html
如上图所示,当第一个变量(userful.....)和第二个变量(very useful)的内存块有重叠时,memmove() 函数可以将第二个变量的值先放入缓冲区,然后再对第一个变量的值进行覆盖。这样做的好处是,以第 20 位的 u 为例,防止 u 没有复制到 25 位时,值就被改写了。这里的矛盾在于,第15位的 v 要复制到第20位 u,第20位 u 要复制到第25位 i,有个前后顺序的问题,应该先将 20位的 u 复制到 25位的 i 上,再把 15 位的 v 复制到 20 位 u 上。