前言
C语言提供了一些内存操作函数,这些函数允许你在内存中执行各种操作,如复制、设置、比较等。与处理字符串函数不同的是,内存处理函数可对多种类型进行处理。接下来我们讲解并模拟实现这些函数。
文章目录
1、memcpy的使用
描述
C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。
声明
void *memcpy(void *str1, const void *str2, size_t n)
参数
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
n – 要被复制的字节数。
返回值
该函数返回一个指向目标存储区 str1 的指针。
使用实例:
// 将字符串复制到数组 dest 中
#include <stdio.h>
#include <string.h>
int main ()
{
const char src[50] = "hello world";
char dest[50];
memcpy(dest, src, strlen(src)+1);
printf("dest = %s\n", dest);
return(0);
}
运行结果:
1.1 memcpy的模拟实现
void* memcpy(void* dst, const void* src, size_t count)
{
void* ret = dst;
assert(dst);
assert(src);
while (count--) {
//*(char*)dst++ = *(char*)src++这种写法是未定义的,在某些编译是不允许的
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return ret;
}
2、memmove的使用
描述
C 库函数 void *memmove(void *str1, const void *str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。 如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
声明
void *memmove(void *str1, const void *str2, size_t n)
参数
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
n – 要被复制的字节数。
返回值
该函数返回一个指向目标存储区 str1 的指针。
使用实例
#include <stdio.h>
#include <string.h>
int main()
{
const char dest[] = "oldstring";
printf("old dest = %s\n", dest);
memmove(dest+2, dest, 5);
printf("new dest = %s\n", dest);
return(0);
}
运行结果
2.1 memmove的模拟实现
void* my_memmove(void* dst, const void* src, size_t count)
{
// 保存目标地址的指针,以便后面返回
void* ret = dst;
// 如果目标地址在源地址之后,或者它们没有重叠的部分
if (dst <= src || (char*)dst >= ((char*)src + count)) {
// 从前往后逐字节复制数据
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1; // 移动目标和源指针到下一个字节
src = (char*)src + 1;
}
}
else {
// 如果目标地址在源地址之前,且它们有重叠的部分
dst = (char*)dst + count - 1; // 移动目标和源指针到最后一个字节
src = (char*)src + count - 1;
// 从后往前逐字节复制数据
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst - 1; // 移动目标和源指针到前一个字节
src = (char*)src - 1;
}
}
// 返回目标地址的起始指针
return ret;
}
3、memset的使用
描述
C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
声明
void *memset(void *str, int c, size_t n)
参数
str – 指向要填充的内存块。
c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
n – 要被设置为该值的字符数。
返回值
该值返回一个指向存储区 str 的指针。
实例
#include <stdio.h>
#include <string.h>
int main()
{
char str[50]="hello world";
memset(str, '$', 7);
puts(str);
return 0;
}
运行结果
3.1 memset的模拟实现
void* my_memset(void* ptr, int value, size_t num) {
unsigned char* byte_ptr = (unsigned char*)ptr;
// 将value强制转换为unsigned char类型以确保正确设置每个字节
unsigned char byte_value = (unsigned char)value;
for (size_t i = 0; i < num; i++) {
*byte_ptr = byte_value;
byte_ptr++;
}
return ptr;
}
4、memcmp的使用
描述
C 库函数 int memcmp(const void *str1, const void *str2, size_t n)) 把存储区 str1 和存储区 str2 的前 n 个字节进行比较。
声明
int memcmp(const void *str1, const void *str2, size_t n)
参数
str1 – 指向内存块的指针。
str2 – 指向内存块的指针。
n – 要被比较的字节数。
返回值
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
实例
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[15];
char str2[15];
int ret;
memcpy(str1, "abcdef", 6);
memcpy(str2, "ABCDEF", 6);
ret = memcmp(str1, str2, 5);
if(ret > 0)
{
printf("str2 小于 str1");
}
else if(ret < 0)
{
printf("str1 小于 str2");
}
else
{
printf("str1 等于 str2");
}
return(0);
}
运行结果
4.1 memcmp的模拟实现
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
const unsigned char* byte_ptr1 = (const unsigned char*)ptr1;
const unsigned char* byte_ptr2 = (const unsigned char*)ptr2;
for (size_t i = 0; i < num; i++) {
if (*byte_ptr1 != *byte_ptr2) {
// 如果发现不相等的字节,返回它们的差值
return (*byte_ptr1 - *byte_ptr2);
}
byte_ptr1++;
byte_ptr2++;
}
// 如果没有找到不相等的字节,返回0表示相等
return 0;
}
以上函数均包含在C的标准库—<string.h>
信息来源:C语言标准库–<string.h>
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。