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即可以是数组方式声明的,也可以是指针方式声明的。
二、举例程序:

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值