【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'

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


相关推荐
QMCY_jason37 分钟前
Ubuntu 安装RUST
linux·ubuntu·rust
慕雪华年41 分钟前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch
苦逼IT运维1 小时前
YUM 源与 APT 源的详解及使用指南
linux·运维·ubuntu·centos·devops
仍有未知等待探索1 小时前
Linux 传输层UDP
linux·运维·udp
zeruns8021 小时前
如何搭建自己的域名邮箱服务器?Poste.io邮箱服务器搭建教程,Linux+Docker搭建邮件服务器的教程
linux·运维·服务器·docker·网站
卑微求AC1 小时前
(C语言贪吃蛇)16.贪吃蛇食物位置随机(完结撒花)
linux·c语言·开发语言·嵌入式·c语言贪吃蛇
Hugo_McQueen2 小时前
pWnos1.0 靶机渗透 (Perl CGI 的反弹 shell 利用)
linux·服务器·网络安全
XY.散人2 小时前
初识Linux · 文件(1)
linux·运维·服务器
叶北辰CHINA3 小时前
nginx反向代理,负载均衡,HTTP配置简述(说人话)
linux·运维·nginx·http·云原生·https·负载均衡
不惑_3 小时前
在 Ubuntu 安装 Python3.7(没有弯路)
linux·运维·ubuntu