【C语言进阶(四)】内存操作函数讲解

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C语言学习分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多C语言知识

🔝🔝



内存操作函数

  • [1. 前言🚩](#1. 前言🚩 "#1__15")
  • [2. memcpy介绍🚩](#2. memcpy介绍🚩 "#2_memcpy_40")
    • [2.1 memcpy的缺点🏁](#2.1 memcpy的缺点🏁 "#21__memcpy_65")
  • [3. memmove函数介绍🚩](#3. memmove函数介绍🚩 "#3_memmove_74")
    • [3.1 memmove的缺陷🏁](#3.1 memmove的缺陷🏁 "#31_memmove_103")
  • [4. memset函数介绍🚩](#4. memset函数介绍🚩 "#4_memset_112")
  • [5. memcmp函数介绍🚩](#5. memcmp函数介绍🚩 "#5_memcmp_143")
  • [6. memchr函数介绍🚩](#6. memchr函数介绍🚩 "#6_memchr_172")
  • [7. 总结及拓展🚩](#7. 总结及拓展🚩 "#7__205")

1. 前言🚩

我最近在刷题的时候全然不知的写出了一个bug代码,它大概意思是这样的:

c 复制代码
int a[]={1,2,3};
int b[]={0,0,0};
strcpy(a,b);

我想将b数组拷贝到a数组去,我第一时间想到了strcpy函数。

  • 但是显然strcpy是操作字符串的
  • 那么我们有没有什么办法能够像strcpy函数一样操作整型呢?

天空一声巨响,我们的内存操作函数闪亮登场!今天的主角有三个:

  1. 男主小帅:memcpy函数 😎
  2. 女主小美:memmove函数 😎
  3. 猛男丧彪:memset函数 😎

还附送两个配角:

  1. 友情出演: memcmp函数 ✔
  2. 群众演员: memchr函数 ✔

2. memcpy介绍🚩

memcpy的函数原型:

功能:从source的起始位置复制num个字节到destination的内存起始位置

用法示例:

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	int a[5] = { 1,2,3,4,5 };
	int b[3] = { 33,22,11 };
	memcpy(a, b, sizeof(int) * 3);//将数组b往后12个字节(3个整型)的内容拷贝到数组a
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

值得注意的是:memcpy函数返回void* 类型指针,并且接受变量的类型也是void *,如果你想了解void * 这个变量,可以跳转 C语言void*详解


2.1 memcpy的缺点🏁

memcpy函数中的两个参数在内存中的位置是不能发生重叠的.

什么意思?举个例子:

既然memcpy函数有缺陷,是时候让我们的女主:memmove函数出来解决问题了!


3. memmove函数介绍🚩

memmove的函数原型:

功能:从source的起始位置复制num个字节到destination的内存起始位置

memmove和memcpy函数的功能是一样的,只不过memmove函数的source和destination指向的空间可以重叠

用法示例:

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	int a[9] = { 1,2,3,4,5,6,7,8,9 };
	memmove(a, a + 5, 16);

	for (int i = 0; i < 9; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

这个结果符合我们的预期:
(覆盖了前面的1234后,后面的56789照常打印)


3.1 memmove的缺陷🏁

  • memmove函数无法使用某些机器所提供的特殊字节-字符串处理指令来实现
    👍 👍 👍
  • 导致的结果:memmove会比memcpy的效率低一些
    👍 👍 👍
  • 如果源和目标参数真的可能存在重叠,就应该使用memmove!

4. memset函数介绍🚩

memset的函数原型:

功能:把从ptr开始的num个字节的值都设置为value

用法示例:

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	char a[6] = { 'a','b','c','d','e','f'};
	memset(a, '-', 3);

	for (int i = 0; i < 6; i++)
	{
		printf("%c ", a[i]);
	}
	return 0;
}

结果和我们预期的一样:
(将前三个字节的内容改成 ' - ' )

注意,这里内存操作函数中参数num的单位都是字节,如果你想要修改一个整型数组的前n个值,别忘了用n乘以整型的长度!


5. memcmp函数介绍🚩

memcmp的函数原型:

功能:memcmp对两段内存ptr1和ptr2的内容进行比较,共比较num个字节

用法示例:

c 复制代码
#include <stdio.h>
#include <string.h>
int main ()
{
  char buffer1[] = "DWgaOtP12df0";
  char buffer2[] = "DWGAOTP12DF0";
  int n = memcmp( buffer1, buffer2, sizeof(char)*5);
  return 0;
}

memcmp的返回类型和strcmp一样:

  • 负数代表ptr1小于ptr2. 👀
  • 正数代表ptr1大于ptr2. 👀
  • 0代表它们两个相同👀

值得注意的是:这些值是按照无符号字符逐字节比较,所以它用于比较不是单字节数据如整数,浮点数时可能给出不可预料的结果.


6. memchr函数介绍🚩

memchr的函数原型:

功能:

  • 从ptr开始,查找value第一次出现的位置
  • 共查找num个字节.
  • 如果找到,返回一个指向该位置的指针
  • 如果没找到,返回NULL.

用法示例:

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	char a[6] = { 'a','b','c','d','e','f'};
	char* p = memchr(a, 'd', sizeof(char) * 6);//在数组a中查找字符d第一次出现的位置
	for (int i = 0; i < 3; i++)//这里返回一个指针指向字符d,并将这个指针赋值给p
	{
		printf("%c ", p[i]);
	}
	return 0;
}

结果也符合我们的预期:


7. 总结及拓展🚩

总的来说这一板块还是没有难度的,所有的内存操作函数需要包含的头文件是:string.h.关于内存操作函数我们就完结撒花啦!

函数原型出处: C\C++字典:cplusplus

下面我给大家拓展一些字符操作函数:
(在做题时可以节省时间)

比如:

  • 判断字符是否为0~9的数字
  • 判断字符是不是字母
  • 判断是否为大写字母(小写)
  • 等等...
函数 满足下面条件就返回真
isspace 空白字符:空格' ',换页'\f',换行'\n',回车'\r',制表符'\t'
isdigit 十进制数字: 0 ~ 9
islower 小写字母: a ~ z
isupper 大写字母: A ~ Z
isalpha 字母 : a ~ z 或 A ~ Z
isalnum 字母或者数字: a ~ z,A ~ Z,0 ~ 9
ispunct 标点符号,任何不属于数字或字母的图形

两个转换函数:

  • 大写字母转小写字母: tolower
  • 小写字母转大写字母: toupper

如:

c 复制代码
char x = tolower('A');//变量x存储的是字符 'a'

最后,看完这一节的内容后
下次遇见字符串拷贝
你会用什么函数来完成任务?
来参与一下投票吧!


相关推荐
2035去旅行2 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1233 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡3 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.7 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道7 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.10 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落12 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨12 小时前
WSL2的安装与使用
linux·wsl
微小的鱼12 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng12 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器