c语言动态内存分配

本文详细介绍了C语言中动态内存分配的基本概念,包括malloc、calloc、realloc和free函数的使用方法,以及如何避免内存泄漏。文章还提供了一个示例程序,展示了如何动态分配和释放double数组的内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态内存分配是许多高级程序设计技巧的关键。

所有程序都必须留下足够的内存来存储程序使用的数据。这些内存中,有些是自动分配的(栈),有些是在编译时就确定好的(静态区),c语言还可以实现动态的/运行时的内存分配,提高程序的灵活性。

c语言动态内存分配的主要工具是stdlib.h中的malloc()、calloc()和free()函数。

malloc()函数会向操作系统请求内存块,并返回内存块的首地址。可以用一个指针变量保存这个地址。
这里注意的是,这个内存块是匿名的,也就是不像int x 那样,x为内存地址的标识符。
地址的类型为通用指针void *,我们需要为其强制类型转换。但申请失败时,返回值为NULL,所以我们申请完内存后,需要判断是否申请成功。
malloc的参数为内存的字节大小。

calloc()函数与malloc函数大体相同,calloc函数接受两个参数,单元数量和单元大小,并且内存块中的值为0;

有借有还再借不难,free()函数用于释放申请的内存。如果忘记释放,那么可能把指向该内存块的指针搞丢了,我们再也无法操作这个内存,这就是内存泄露问题。

下面是c primer plus 中的一个示例程序,程序动态分配由用户制定大小和值的double 数组,并把数组打印出来

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	double *ptd = NULL;
	int max;
	int number;
	int i = 0;

	puts("What is the maximun number of type double entries?");
	
	if(scanf("%d", &max)!=1)
	{	
		puts("Number not correctly entered --bye.");
		exit(EXIT_FAILURE);
	}
	
	ptd = (double *) malloc(max*sizeof(double));
	if(ptd == NULL)
	{
		puts("Memory allocation failed. Goodbye.");
		exit(EXIT_FAILURE);	
	}	
	
	puts("Enter the values (q to quit):");

	while(i < max && scanf("%lf",&ptd[i]) == 1)
		++i;
	
	printf("Here are you %d entries:\n",number = i);
	for(i=0 ; i < number ;i++)
	{
		printf("%7.2f",ptd[i]);
			if(i%7 ==6)
			putchar('\n');	
	}	
	
	if(i%7 !=0)
		putchar('\n');
	puts("Done.");
	free(ptd);
	ptd = NULL;

	return 0;
}

下面是转载的

calloc(), malloc(), realloc(), free(),alloca()

内存区域可以分为栈、堆、静态存储区和常量存储区,局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。
利用指针,我们可以像汇编语言一样处理内存地址,C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h。

四个函数之间的有区别,也有联系,我们应该学会把握这种关系,从而编出精炼而高效的程序。

在说明它们具体含义之前,先简单从字面上加以认识,前3个函数有个共同的特点,就是都带有字符”alloc”,就是”allocate”,”分配”的意思,也就是给对象分配足够的内存,” calloc()”是”分配内存给多个对象”,” malloc()”是”分配内存给一个对象”,”realloc()”是”重新分配内存”之意。”free()”就比较简单了,”释放”的意思,就是把之前所分配的内存空间给释放出来。
void *calloc(size_t nobj, size_t size);

分配足够的内存给nobj个大小为size的对象组成的数组, 并返回指向所分配区域的第一个字节的指针;
若内存不够,则返回NULL. 该空间的初始化大小为0字节.
char *p = (char *) calloc(100,sizeof(char));

void *malloc(size_t size);

分配足够的内存给大小为size的对象, 并返回指向所分配区域的第一个字节的指针;
若内存不够,则返回NULL. 不对分配的空间进行初始化.
char *p = (char *)malloc(sizeof(char));

void *realloc(void *p, size_t size);

将p所指向的对象的大小改为size个字节.
如果新分配的内存比原内存大, 那么原内存的内容保持不变, 增加的空间不进行初始化.
如果新分配的内存比原内存小, 那么新内存保持原内存的内容, 增加的空间不进行初始化.
返回指向新分配空间的指针; 若内存不够,则返回NULL, 原p指向的内存区不变.
char *p = (char *)malloc(sizeof(char));
p= (char *)realloc(p, 256);

void free(void *p);

释放p所指向的内存空间; 当p为NULL时, 不起作用.
p必先调用calloc, malloc或realloc.

值得注意的有以下5点:

(1)通过malloc函数得到的堆内存必须使用memset函数来初始化

malloc函数分配得到的内存空间是未初始化的。因此,一般在使用该内存空间时,要调用另一个函数memset来将其初始化为全0,memset函数的声明如下:void * memset (void * p,int c,int n) ;

该函数可以将指定的内存空间按字节单位置为指定的字符c,其中,p为要清零的内存空间的首地址,c为要设定的值,n为被操作的内存空间的字节长度。如果要用memset清0,变量c实参要为0。

malloc函数和memset函数的操作语句一般如下:

int * p=NULL;

p=(int*)malloc(sizeof(int));

if(p==NULL)

printf(“Can’t get memory!\n”);

memset(p,0,siezeof(int));

(2)使用malloc函数分配的堆空间在程序结束之前必须释放

从堆上获得的内存空间在程序结束以后,系统不会将其自动释放,需要程序员来自己管理。一个程序结束时,必须保证所有从堆上获得的内存空间已被安全释放,否则,会导致内存泄露。

我们可以使用free()函数来释放内存空间,但是,free函数只是释放指针指向的内容,而该指针仍然指向原来指向的地方,此时,指针为野指针,如果此时操作该指针会导致不可预期的错误。安全做法是:在使用free函数释放指针指向的空间之后,将指针的值置为NULL。

(3)calloc函数的分配的内存也需要自行释放

calloc函数的功能与malloc函数的功能相似,都是从堆分配内存,它与malloc函数的一个显著不同时是,calloc函数得到的内存空间是经过初始化的,其内容全为0。calloc函数适合为数组申请空间,可以将size设置为数组元素的空间长度,将n设置为数组的容量。

(4)如果要使用realloc函数分配的内存,必须使用memset函数对其内存初始化

realloc函数的功能比malloc函数和calloc函数的功能更为丰富,可以实现内存分配和内存释放的功能。realloc 可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。realloc 并不保证调整后的内存空间和原来的内存空间保持同一内存地址。相反,realloc 返回的指针很可能指向一个新的地址。

所以,在代码中,我们必须将realloc返回的值,重新赋值给 p :

p = (int *) realloc(p, sizeof(int) *15);

甚至,你可以传一个空指针(0)给 realloc ,则此时realloc 作用完全相当于malloc。

int* p = (int *)realloc (0,sizeof(int) * 10); //分配一个全新的内存空间,

这一行,作用完全等同于:

int* p = (int *)malloc(sizeof(int) * 10);

(5)关于alloca()函数

还有一个函数也值得一提,这就是alloca()。其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。其优点是:当 函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持alloca 函数。尽管如此,很多软件包还是使用alloca函数,也有很多系统支持它。

总结:应用时候需要记得,只有calloc可以指定个数和大小,而且能够对分配内存进行初始化,其余函数均不会对内存进行初始化工作,需要自行调用memset()函数.

<think>好的,用户现在问的是“vivo什么时候接入deepseek”。首先,我需要确认这两个实体:vivo和deepseek。vivo是一家中国的智能手机和电子产品制造商,而DeepSeek可能指的是深度求索(DeepSeek)人工智能公司,专注于AI大模型的研究和应用。用户的问题可能是想知道vivo何时与DeepSeek合作或整合其技术。 接下来,我需要查找相关的最新信息。根据之前的资料,vivo2023年11月发布了自研的蓝心大模型,并强调自主研发,可能没有明确提到与DeepSeek的合作。另外,DeepSeek作为独立的AI公司,可能有与其他厂商合作,但需要确认是否有公开信息显示与vivo的合作时间。 用户可能的需求是了解vivo是否采用了DeepSeek的技术,或者何时开始合作。可能的背景是用户对手机AI功能感兴趣,或者关注企业间技术合作动态。需要检查是否有官方公告、新闻稿或权威媒体报道过两者的合作。如果找不到确切信息,应如实告知用户目前没有公开信息,并建议关注官方渠道获取最新消息。 另外,可能存在混淆,比如是否用户将DeepSeek与其他公司(如百度、商汤等)混淆了,需要确认。同时,考虑到AI领域的合作通常会有技术整合或联合发布产品,可以推测用户可能对vivo手机中的AI功能来源感兴趣,但需根据现有资料回答,避免猜测。</think>截至2024年7月,**vivo官方并未公开宣布与深度求索(DeepSeek)人工智能公司达成合作或技术接入的具体时间**。以下是相关背景和信息的梳理: --- ### **背景说明** 1. **vivo的AI布局** - vivo近年来重点投入AI技术研发,尤其在2023年推出自研的**蓝心大模型(BlueLM)**,并应用于手机端侧(如语音助手、图像处理等),强调自主研发能力。 - 其AI能力主要通过自有团队和合作伙伴(如高通、联发科芯片的AI模块)实现,但未提及与DeepSeek的直接合作。 2. **DeepSeek的技术方向** - 深度求索(DeepSeek)是一家专注AI大模型研发的中国公司,主要面向B端提供行业解决方案,合作案例多集中在金融、医疗等领域,与手机厂商的公开合作较少。 --- ### **可能关联点** - **技术间接整合**: 不排除vivo通过第三方技术供应商或开源社区使用DeepSeek的部分算法(如通用AI模型),但此类合作通常不会单独官宣。 - **行业动态推测**: 2024年国内AI大模型竞争加剧,手机厂商可能探索与专业AI公司合作,但目前尚无vivo与DeepSeek的明确进展。 --- ### **建议关注渠道** 若需获取最新信息,可关注以下来源: 1. **vivo官方发布会**(如新机发布、开发者大会)。 2. **DeepSeek官网/社交媒体**的技术合作公告。 3. **权威科技媒体**(如36氪、晚点LatePost等)的行业报道。 --- **总结**:目前两者无公开合作信息,vivo的AI能力以自研为主。未来合作可能性取决于双方技术需求与战略布局,建议以官方消息为准。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值