这三个函数实在是太经典了,不得不自己来实现一遍。
三个函数的原型如下:
void* memset(void *des, int val, size_t size) void * memcpy(void *des, const void* src, size_t size) void * memmove(void *des, const void *src, size_t size)
void* memset(void *des, int val, size_t size) { void *start = des; while (size--) { *(char*) des = (char) val; des = (char *) des + 1; // (char*) des++; // des = (char* )des + 1; } return start; } void * memcpy(void *des, const void* src, size_t size) { void *ret = des; while (size--) { *(char *) des = *(char *) src; des = (char *)des + 1; src = (char *)src + 1; // (char *) des++; // (char *) src++; } return ret; } void * memmove(void *des, const void *src, size_t size) { void *ret = des; if (des < src || (char *) des > (char *) src + size - 1) { while (size--) { *(char *) des = *(char *) src; des = (char *) des + 1; src = (char *)src + 1; // (char *) src++; // (chr *) des ++; } }else{ des = (char *)des + size - 1; src = (char *)src + size - 1; while (size -- > 0){ *(char *) des = *(char *) src; // (char *) des--; // (char *) src--; des = (char *)des - 1; src = (char *)src - 1; } } return ret; }
看起来不爽。
注意事项:
(1)使用memset的时候,要把最后一位或者最后一位的下一位置为‘\0’;
char buffer[20] = "hello"; memset(buffer, '1', sizeof(char)*20); printf("%s\n",buffer); 运行结果:111111111111111111110@ char buffer[20] = "hello"; memset(buffer, '1', sizeof(char)*20); buffer[20] = '\0'; printf("%s\n",buffer); 运行结果:11111111111111111111
(2)memcpy和strcpy的区别:
实际上区别只有一个,strcpy的操作对象只能是char *,而memcpy操作的对象是void *。(什么类型的都可以)。实际上,在memcpy的实现上,都是将(void *)装换成为了(char *)来做的,其实跟strcpy一样。
(3)memmove和memcpy的区别:
区别就是memmove要考虑内存区间重叠的情况,而memcpy不会。
关于这个问题,可以用下面的图片来解释:
内存区间重叠的情况如下和不会出现内存区间重叠的情况:
假设des为src + 2,如果按照memcpy处理,从头开始拷贝,就要出现下面的悲剧:
src的内存都被污染了,而且如果这时候打印*des开头的内存,仍然会出现未定义的情况:因为'\0'被覆盖了。
char buffer5[10] = "1234"; memcpy(buffer5 + 2, buffer5, sizeof(buffer5)); printf("%s\n", buffer5); char buffer6[10] = "1234"; memmove(buffer6 + 2, buffer6, sizeof(buffer6)); printf("%s\n",buffer6 + 2);运行结果: