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

发布于:2024-12-21 ⋅ 阅读:(138) ⋅ 点赞:(0)


1. 前言🚩

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

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的内存起始位置

用法示例:

#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指向的空间可以重叠

用法示例:

#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

用法示例:

#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个字节

用法示例:

#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.

用法示例:

#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

如:

char x = tolower('A');//变量x存储的是字符 'a'


网站公告

今日签到

点亮在社区的每一天
去签到