当前位置: 首页 > article >正文

C语言第15讲:C语言内存函数

1. memcpy 使用和模拟实现

1.1 函数定义

void * memcpy(void *dest, const void *src, size_t n);

1.2 功能

将源内存块 src 的前 n 个字节复制到目标内存块 dest

1.3 注意事项

  1. 目标区域与源区域不能重叠。若存在重叠,应使用 memmove
  2. 这个函数在遇到'\0' 的时候并不会停下来。
  3. 返回值:返回 dest 指针。

1.4 示例代码

#include <stdio.h>
#include <string.h>

int main() 
{
    char src[] = "Hello, World!";
    char dest[20];

    memcpy(dest, src, strlen(src) + 1); // 复制包括结束符'\0'
    printf("Copied string: %s\n", dest);

    return 0;
}

输出:

Copied string: Hello, World!

1.5 模拟实现

void * memcpy ( void * dst, const void * src, size_t count)
{
	void * ret = dst;
	assert(dst);
	assert(src);
	/*
	* copy from lower addresses to higher addresses
	*/
	while (count--) 
	{
		*(char *)dst = *(char *)src;
		dst = (char *)dst + 1;
		src = (char *)src + 1;
	}
	return(ret);
}

2. memmove 使用和模拟实现

2.1 函数定义

void *memmove(void *dest, const void *src, size_t n);

2.2 功能

memcpy 类似,但支持 重叠区域 的安全复制。

2.3 注意事项

  1. destsrc 有重叠时,确保数据不会被破坏。
  2. 返回值:返回 dest 指针。

2.4 示例代码

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "abcdef";

    memmove(str + 2, str, 4); // 将前4个字符移动到位置2开始
    printf("After memmove: %s\n", str); // 输出 "ababcd"

    return 0;
}

输出:

After memmove: ababcd

2.5 模拟实现

void * memmove ( void * dst, const void * src, size_t count)
{
	void * ret = dst;
	if (dst <= src || (char *)dst >= ((char *)src + count)) 
	{
		/*
		* Non-Overlapping Buffers
		* copy from lower addresses to higher addresses
		*/
		while (count--) {
			*(char *)dst = *(char *)src;
			dst = (char *)dst + 1;
			src = (char *)src + 1;
		}
	}
	else 
	{
		/*
		* Overlapping Buffers
		* copy from higher addresses to lower addresses
		*/
		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 函数的使用

3.1 函数定义

void * memset(void *s, int c, size_t n);

3.2 功能

将内存块 s 的前 n 个字节设置为值 c(以无符号字符解释)。

3.3 注意事项

  1. 通常用于初始化内存或清零操作。
  2. 返回值:返回 s 指针。

3.4 示例代码

#include <stdio.h>
#include <string.h>

int main() {
    char buffer[10];
    memset(buffer, '*', sizeof(buffer) - 1); // 用'*'填充
    buffer[9] = '\0'; // 添加字符串结束符
    printf("Buffer: %s\n", buffer);

    return 0;
}

输出:

Buffer: *********

3.5 模拟实现

void *my_memset(void *s, int c, size_t n) {
    unsigned char *p = (unsigned char *)s;
	int i;
    for (i = 0; i < n; i++) {
        p[i] = (unsigned char)c;
    }

    return s;
}

4. memcmp 函数的使用

4.1 函数定义

int memcmp(const void *s1, const void *s2, size_t n);

4.2 功能

比较两块内存的前 n 个字节。

  • 返回值:
    • 0:两块内存相等。
    • <0s1 小于 s2
    • >0s1 大于 s2

在这里插入图片描述

4.3 注意事项

  1. 按字节逐一比较。
  2. 常用于比较数组或内存块。

4.4 示例代码

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "abcdef";
    char str2[] = "abcdeg";

    int result = memcmp(str1, str2, 6);
    if (result == 0) {
        printf("str1 and str2 are equal.\n");
    } else if (result < 0) {
        printf("str1 is less than str2.\n");
    } else {
        printf("str1 is greater than str2.\n");
    }

    return 0;
}

输出:

str1 is less than str2.

4.5 模拟实现

int my_memcmp(const void *s1, const void *s2, size_t n) {
    const unsigned char *p1 = (const unsigned char *)s1;
    const unsigned char *p2 = (const unsigned char *)s2;
	int i;
    for (i = 0; i < n; i++) 
    {
        if (p1[i] != p2[i]) {
            return p1[i] - p2[i];
        }
    }

    return 0;
}

5. 总结

  • memcpy:高效复制,但不支持重叠区域。
  • memmove:支持重叠区域复制。
  • memset:初始化或设置内存。
  • memcmp:比较两块内存的内容。

以上函数均以字节为单位操作,灵活且高效。在实际开发中,注意确保指针合法性和内存边界,以避免未定义行为。

—完—


http://www.kler.cn/a/415788.html

相关文章:

  • 【LeetCode每日一题】——189.轮转数组
  • MyBatis-Plus忽略多租户隔离自定义注解
  • 麒麟性能评估优化
  • 命令行使用ssh隧道连接远程mysql
  • 浏览器开发工具
  • java-分而治之算法
  • shell第二次作业
  • 程成本控制系统如何跟工程现场管理结合起来?
  • 【Unity-如何提高物理引擎的高精度模拟】
  • 【Python爬虫实战】深入解析 Scrapy:从阻塞与非阻塞到高效爬取的实战指南
  • [Python/网络安全] Git漏洞之Githack工具基本安装及使用详析
  • Pytorch使用手册-使用 TensorBoard 可视化模型、数据和训练过程(专题十)
  • JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】
  • 如何选择黑白相机和彩色相机
  • GAN是一种自监督模型那在判别器中,同时输入生成器生成的SR与真实值HR作比较的话,不就是将HR作为SR的标签吗,如何体现自监督学习呢
  • YOLOv11融合Inner-IoU及相关改进思路
  • I/O流综合练习题
  • 摄影相关常用名词
  • springboot343大学生选修选课系统的设计与实现(论文+源码)_kaic
  • 物联网环境中NDN协议的性能比较分析
  • CQ 社区版 2024.11 | 新增“审批人组”概念、可通过SQL模式自定义审计图表……
  • 详解登录MySQL时出现SSL connection error: unknown error number错误
  • 网络安全、Web安全、渗透测试之笔经面经总结(三)
  • net9 abp vnext 多语言通过数据库动态管理
  • Ubuntu安装不同版本的opencv,并任意切换使用
  • 从单一设备到万物互联:鸿蒙生态崛起的未来之路