C语言从头学34——内存管理(二)

一、与内存管理相关的函数(续)(编号另起)

1、restrict 说明符

restrict的意思是限制。用在声明指针变量上,含义是某内存区块只有当前指针一种访问方式,其它指针不能读写该块内存。这种指针称为"限制指针"。

使用方法:int * restrict ptr = malloc(sizeof(int));

说明:我这里经过反复试验,restrict编译器不能识别,后将restrict改成__restrict(加双下划线)编译正常,但 restrict 在程序编写、编译、运行过程中应报错而未报错;从网上查了原因讲是VS造成的。有解决办法的朋友请私信指教,不胜感激。

2、memcpy()函数的使用

功能:将一块内存(内容)拷贝到另一块内存。

使用格式:memcpy(参1,参2,参3);

参1 目标内存区指针

参2 源内存区指针

参3 拷贝字节数(size_t类型即正整型)

返回值:返回目标内存区指针

说明:

a. memcpy定义在<string.h>中,编译器如不能识别这个函数,请包含string.h。

b. 目标区指针、源区指针可以是任意类型(包含void* 类型),但目标区大小不能小于拷贝字节数,拷贝字节数不能大于源区字节数,否则会内存溢出。不同类型所占字节数不同、同类型不同编译器所占字节可能不同,故拷贝字节数还是通过 sizeof 计算为好。

c. 返回值返回的指针与pDest指针指向相同,故没有必要接收这个指针;如接收后使用可能还会导致运行异常。

d. memcpy可以替代strcpy进行字符串拷贝,速度会快些,但它不检查字符串尾的\0,拷贝长度需要自己考虑。

e. 如要将一段内存原样复制到另一段内存中,由于memcpy是按字节操作的,所以可以不管原来的数据类型,统一对目标区内存指针、源区指针定义成char* 类型(逐字节进行),就可以完成原样复制。这种办法可以用来复制文件,不需要关心文件自身的格式。

f. 复制内存区域的字节数,如是赋值字符串,应注意 "\0" 要计算进去。

3、memmove()函数的使用

功能:将一段内存数据复制(移动)到另一段内存。与memcpy的主要区别是:它允许目标区域与源区域有重叠,重叠区域原有内容会被更改。

使用格式:memmove(参1,参2,参3);

参1 目标内存区(字符数组)指针

参2 源内存区指针

参3 复制(移动)字节数(size_t类型即正整型)

返回值:返回目标地址的指针。

说明:

a. memmove函数定义在<string.h>,使用VS2022仅包含 <stdio.h> 运行正常。

b. 参1目标指针实际也是原始数据指针,应使用数组方式声明,以指针方式声明的VS2022运行错误,其它编译器情况不详。

4、memcmp()函数的使用

功能:比较两个内存区域

使用格式:memcmp(参1,参2);

参1 指向第一区域指针

参2 指向第二区域指针

参3 参加比较的字节数

返回值:参1 == 参2 返回0;

参1 > 参2 返回 1;

参1 < 参2 返回 - 1

说明:

a. memcmp也是定义在<string.h>中,具体情况同上。

b. 对于字符串比较,如果参3的值超过字符串实际长度,"\0"也会参加比较

c. 参1、参2即可以是数组方式声明的,也可以是指针方式声明的。

二、举例程序:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	//a. restrict限定符
	int* __restrict ptr = malloc(sizeof(int));
	if (ptr == NULL)return 0;
	*ptr = 3;
	int* p = ptr;
	*p = 5;
	printf("%i  %i\n", *p, *ptr); //restrict未起作用
	//b. memcpy函数
	char* pSource = "abcdefghijklmnopqrstuvwxyz";
	int* pDest = malloc(sizeof(char) * 27);//26个字母加"\0"结束符
	if (pDest == NULL)return 0;
	memcpy(pDest, pSource, sizeof(char) * 27);//完成拷贝,"\0"也在拷贝范围
	printf("%s\n", (char*)pDest); //显示拷贝结果
	//c. memmove函数
	char SN[] = "1111223344556677889900";//字符串中多了两个"2"
	/*
		 分析:如果将"1111"中去掉两个"1",只需将第第三个"1"开始至结尾的部分,重新复制
	 回SN即可,因为memmove允许源区与目标区内存重合。所以源区指针起始位置应指向字符串
	 第三个"1",即SN+2;目标区指针还是SN。关于移动字节数,由于char型一个字符就是一个字节,
	 所以可以用strlen(SN)减去两个准备去掉的再加上一个看不见的"\0"即可。
	*/
	char* pDestSN = SN;
	char* pSourceSN = &SN[2];
	size_t n = strlen(SN) - 2 + 1;
	memmove(pDestSN, pSourceSN, n);
	printf("%s\n", SN); //SN中的字符串已被改变
	//d. memcmp()函数
	char* str1 = "天津市南开区";
	char* str2 = "天津市和平区";
	int myInt1[] = { 1,2,3,4,5 };
	int myInt2[] = { 6,7,8,9,10 };
	int ret = memcmp(str1, str2, 6);
	printf("比较三个汉字返回值:%i\n", ret); //返回值是0(前三个汉字相同)
	ret = memcmp(str1, str2, 12);
	printf("比较六个汉字返回值:%i\n", ret); //返回值是1("南n"排在"和h"后边)
	ret = memcmp(myInt1, myInt2, sizeof(myInt1));
	printf("myInt1与myint2比较返回值:%i", ret); //返回值是-1
	getchar();
	return 0;
}
相关推荐
南东山人1 小时前
一文说清:C和C++混合编程
c语言·c++
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
茶猫_7 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
ö Constancy7 小时前
Linux 使用gdb调试core文件
linux·c语言·vim
lb36363636367 小时前
介绍一下strncmp(c基础)
c语言·知识点
wellnw7 小时前
[linux] linux c实现共享内存读写操作
linux·c语言
珹洺10 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
.Cnn11 小时前
用邻接矩阵实现图的深度优先遍历
c语言·数据结构·算法·深度优先·图论
2401_8582861111 小时前
101.【C语言】数据结构之二叉树的堆实现(顺序结构) 下
c语言·开发语言·数据结构·算法·
寻找码源12 小时前
【头歌实训:利用kmp算法求子串在主串中不重叠出现的次数】
c语言·数据结构·算法·字符串·kmp