重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
基本上C程序的元素存储在内存的时候有3种分配策略:
十余年的肇庆网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都全网营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整肇庆建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“肇庆网站设计”,“肇庆网站推广”以来,每个客户项目都认真落实执行。
静态分配
如果一个变量声明为全局变量或者是函数的静态变量,这个变量的存储将使用静态分配方式。静态分配的内存一般会被编译器放在数据段或代码段来存储,具体取决于实现。这样做的前提是,在编译时就必须确定变量的大小。 以IA32的x86平台及gcc编译器为例,全局及静态变量放在数据段的低端;全局及静态常量放在代码段的高端
自动分配
函数的自动局部变量应该随着函数的返回会自动释放(失效),这个要求在一般的体系中都是利用栈(Stack)来满足的。相比于静态分配,这时候,就不必绝对要求这个变量在编译时就必须确定变量的大小,运行时才决定也不迟,但是C89仍然要求在编译时就要确定,而C99放松了这个限制。但无论是C89还是C99,都不允许一个已经分配的自动变量运行时改变大小。
所以说C函数永远不应该返回一个局部变量的地址。
要指出的是,自动分配也属于动态分配,甚至可以用alloca函数来像分配堆(Heap)一样进行分配,而且释放是自动的。
动态分配
还有一种更加特殊的情况,变量的大小在运行时有可能改变,或者虽然单个变量大小不变,变量的数目却有很大弹性,不能静态分配或者自动分配,这时候可以使用堆(Heap)来满足要求。ANSI C定义的堆操作函数是malloc、calloc、realloc和free。
使用堆(Heap)内存将带来额外的开销和风险。
需要用一个数组来保存用户的输入,但是却不知道用户会输入多少条数据。
(1) 如果设一个太大的数组,则显得浪费内存
(2) 如果设得太小,又怕不够
问题:如何做到恰好够用、又一点不浪费呢?
系统中存在一个内存管理器(MM, Memory Manager),它负责管理一堆闲置内存。它被设计用于解决此类问题。
MM提供的服务:应用程序可以向MM申请(借出)一块指定大小的内存,用完之后再释放(还回)。
应用程序在使用malloc时,要把返回值转换成目标类型。
这块内存和数组没有本质区别,用法完全相同。
需要先计算需要多少字节的内存空间
数组举例子:
释放的时候需要注意, 因为在for循环执行之后,p的地址往前移动了10, 所以需要减去10, 然后再释放p,不然会有问题
// 当销毁时只需要free一次,malloc了几个字节就会free几个字节,和char类型还是int类型无关
free(p);
在一个函数中动态分配的内存,在另一个函数中操作这块内存
(1) MM是一个系统级的东西,所有的应用程序都向同一个MM申请内存。
(2) 何为借出?实际上,在内存被借出时,MM只是把它管理的内存标记了一下,表示该段内存已经被占用。比如,它把每一段被占用的内存给记录下来(首地址,长度)
(p0,n0) (p1, n1) (p2, n2) ...
(3) MM非常慷慨:①只要有人 malloc ,它都同意借出 ②你不归还,它永远不会主动要求你 free 。
(4) MM管理的内存区域称为“堆”Heap
这意味着,用户程序应该自觉得及时 free ,以便不耽误别的应用程序的使用。如果有个应用程序不停地 malloc ,而不 free ,那最终会用光MM的内存。当MM没有更多闲置内存时, malloc 返回 NULL ,表示内存已经用完。
再次重申: 应用程序在malloc之后,应该尽早free !
使用原则:需要的时候再申请,不需要的时候立即释放
实际上,MM对借出的内存块进行标识
(p0, n0) (p1, n1) (p2, n2) ...
它内部已经保证任意两块内存不会“交叠”,即不会重叠,不会把一块内存同时借给两个应用程序使用。
所以,每块内存的首地址都是不同的,在 free 的时候只需要指明首地址即可。
对象指的一块内存
示例:用Citizen表示一个市民,用Car表示一个辆车。他起初没有车,但未来可能有一辆车。
怎么样才算“及时”? “不及时”会怎样?
MM里可用的内存是有限的,你用完了就得尽快还,因为别的应用程序也需要MM的内存。
只借不还,积累到一定程度,MM没有更多内存可用,于是malloc返回NULL。
要还就得全还,否则MM那边处理不了
原因是:MM可能此时没有闲置内存可用。(虽然这种情况一般不会发生)
free之后,该内存交还给MM,该内存不再可用(失效)
不一定要在相同的函数里释放,在应用程序的任意一个角落释放都是有效的。
也就是说:这一块内存被malloc出来之后,完全交给你处置
功能:将 s 中当前位置后面的 n 个字节 (typedef unsigned int size_t )用 ch 替换并返回 s
参数:
参数:
功能:由 src 所指内存区域复制 n 个字节到 dest 所指内存区域。
memmove() 功能用法和 memcpy()) 一样,区别在于: dest
和 src 所指的内存空间重叠时, memmove() 仍然能处理,不过执行效率比 memcpy() 低一些
不知lz有没听说过虚存一说,当源码被编译成二进制文件后,其中的变量,函数的虚拟地址,也就是内存空间中的地址就已确定,在运行时,操作系统为其分配物理内存并添加虚拟地址到物理地址的映射。
再说的多一点,一个进程(运行的程序)可分为若干段:代码段、数据段、堆栈段等,其中函数所操作的空间(也就是局部变量的空间)就位于堆栈段,所谓函数分配内存大小,实际就是堆栈段指针的变化而已。
C语言中内存为分三类:栈区、堆区、静态数据区。
局部变量在栈上分配,函数调用前的栈指针,要和函数返回后的栈指针一样,否则就会出错。
void test(void)
{
char i,a[10];
printf("0x%x", i);
printf("0x%x", a);
printf("0x%x", a+1);
printf("0x%x", a+2);
printf("0x%x", a+3);
}
扩展资料
c语言数组在内存分配
示例:
#includestdio.h
int main()
{
int a[4] = {11,12,13,14};
int b[4] = {21,22,23,24};
int *pa = a;
int i = 0;
while(i8)
{
i++;
printf("now *p value = %d and",*pa);
printf("p addr value = %d \n",pa);
pa++;
}
return 0;
}