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;
}
相关推荐
No0d1es7 小时前
电子学会青少年软件编程(C/C++)5级等级考试真题试卷(2024年6月)
c语言·c++·算法·青少年编程·电子学会·五级
Peter_Deng.11 小时前
Linux 下基于 TCP 的 C 语言客户端/服务器通信详解(三个示例逐步进阶)
服务器·c语言·网络
John.Lewis13 小时前
数据结构初阶(13)排序算法-选择排序(选择排序、堆排序)(动图演示)
c语言·数据结构·排序算法
丑小鸭是白天鹅16 小时前
嵌入式C语言学习笔记之枚举、联合体
c语言·笔记·学习
GUET_一路向前17 小时前
【C语言防御性编程】if条件常量在前,变量在后
c语言·开发语言·if-else·防御性编程
pusue_the_sun18 小时前
数据结构——栈和队列oj练习
c语言·数据结构·算法··队列
Dontla18 小时前
Makefile介绍(Makefile教程)(C/C++编译构建、自动化构建工具)
c语言·c++·自动化
奶黄小甜包18 小时前
C语言零基础第18讲:自定义类型—结构体
c语言·数据结构·笔记·学习
一支闲人19 小时前
C语言相关简单数据结构:双向链表
c语言·数据结构·链表·基础知识·适用于新手小白
John.Lewis19 小时前
数据结构初阶(19)外排序·文件归并排序的实现
c语言·数据结构·排序算法