动态内存开辟须知

C语言中开辟内存有很多种方式,目前我们最常用的也就是数组,但数组是在我们用到他之前就得设定好它的长度,有时很不方便。 我们知道,c语言规定,不允许设定一个未知长度的数组。(但在Linux下可以设定,但也不支持这样做)

例如:

	int x = 5;
	int arr[x];

这样的代码是不正确的,为了填补这一缺口,c语言有了动态内存,c语言提供了几个函数来管理我们的动态内存,这几个函数非常重要,分别为:

1:malloc

void* malloc(size_t size); 

可以看到这个函数的返回类型为void*,为一个空指针(我们前面了解到void* 可以作为返回值和传参但不能直接解引用,所以我们在运用它时需要先将它强制转化为我们想要的指针类型);

  • 这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针;
  • 如果开辟成功,则返回一个指向这块空间的地址;
  • 如果开辟失败,则返回NULL,因此对malloc函数的返回值一定要先检查再使用;

我们知道,以前我们定义的局部变量、函数、数组所需要的空间都是在栈上开辟的,但切记malloc申请的内存是在堆上开辟的栈上的可用资源远远小于堆上的,所以malloc的专长是用来提供大内存需求而且方便管理

堆区向上生长,栈区向下生长

当我们用malloc函数开辟空间时,就会在堆上开辟一段连续的内存空间。

2.free

void free(void* ptr);

有了开辟内存,则就必须要有释放内存!
c语言提供了这样一个函数来释放我们所开辟的内存;
注意:如果ptr不是指向动态内存的,则这种行为未定义;如果ptr为NULL,则函数什么都不会做;

栗子:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* ptr = NULL;
	int num = 0;
	scanf("%d", &num);
	ptr = (int*)malloc(num * sizeof(int));
	if (NULL != ptr)   //必须判断
	{
		int i = 0;
		for (i = 0; i < num; i++)
		{
			*(ptr + i) = i;
		}
	}
	else
	{
		perror("malloc");
	}
	int* p = ptr;
	for (; p < ptr + num; p++)
	{
		printf("%d\n", *p);
	}
 
	free(ptr);      //勿忘
	ptr = NULL;    //防止ptr成为野指针;
	return 0;
}

3.calloc

void* calloc(size_t num, size_t size);

该函数的功能为为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为
该函数与malloc函数基本上没有什么区别,唯一区别就是可以把开辟的内存自动初始化(初始化每个字节为0)

如果要求申请内存需要初始化,这个函数就会很方便。

4.realloc

此函数可以帮助你对申请的内存进行扩展或者缩减,让动态内存管理变得更加灵活。

参数介绍:
ptr是要调整的内存地址,size为调整之后的新大小;
返回值为调整之后的内存起始位置;
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间;

realloc在调整内存时存在两种情况
1.当原有空间的后面有足够大的空间的时候要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化
2.当原有空间的后面没有足够空间时在堆空间上另找一个合适大小的连续空间来 使用。这样函数返回的是一个新的内存地址

栗子:

#include<stdio.h>
int main()
{
	int* ptr = malloc(100);
	if (ptr != NULL)
	{
		;//执行任务
	}
	else
	{
		perror("malloc");
		//或者 exit(EXIT_FAILURE);
	}
	//第一种方法扩展
	//ptr = realloc(ptr, 1000);     //第一种方法;(可能会造成内存泄漏)
 
	//第二种方法扩展
	int *p = realloc(ptr, 1024);
	if (p != NULL)
	{
		ptr = p;
	}
	else
	{
		perror("realloc");
	}
	//执行任务
 
	free(ptr);
	p = NULL;
	return 0;
}

我们在使用realloc时,一定要判断他返回的值,不然如果开辟失败,则会返回NULL,第一种方法的话,ptr就指向了NULL,原来的指针就找不到了,free不掉了,就造成了内存泄漏

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值