嵌入式Linux上C语言编程实践--第9章动态内存堆与栈_第1页
嵌入式Linux上C语言编程实践--第9章动态内存堆与栈_第2页
嵌入式Linux上C语言编程实践--第9章动态内存堆与栈_第3页
嵌入式Linux上C语言编程实践--第9章动态内存堆与栈_第4页
嵌入式Linux上C语言编程实践--第9章动态内存堆与栈_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第四部分第四部分 C语言高级编程语言高级编程 第9章 动态内存的堆与栈 第10章 函数指针的使用 第11章 回调函数的使用 第第12章章 C语言实现对象编程语言实现对象编程2第第9 9章章 动态内存的堆与栈动态内存的堆与栈在嵌入式在嵌入式C语言程序开发中,一个非常重要的语言程序开发中,一个非常重要的内容就是内存的使用,尤其是动态内存的使用内容就是内存的使用,尤其是动态内存的使用。C语言中动态内存主要使用堆和栈来实现。语言中动态内存主要使用堆和栈来实现。本章主要内容:本章主要内容:lC语言中程序的存储区域语言中程序的存储区域l动态内存的堆与栈的特性动态内存的堆与栈的特性lC语言语言与堆、栈的对应

2、关系语言语言与堆、栈的对应关系l堆和栈使用的对比堆和栈使用的对比9.1 程序内存区域的使用 9.1.1 静态内存与动态内存静态内存与动态内存 C语言程序中数据所使用的内存分类:语言程序中数据所使用的内存分类:l 静态数据存储区静态数据存储区u只读数据区(只读数据区(RO Data)u已初始化的读写数据区(已初始化的读写数据区(RW Data)u未初始化的读写数据区(未初始化的读写数据区(BSS) 它们都是在程序的编译它们都是在程序的编译-连接阶段确定的,在程序运行的初始化阶连接阶段确定的,在程序运行的初始化阶段,静态存储区将在内存中开辟,其段,静态存储区将在内存中开辟,其大小和位置在程序的运行

3、过大小和位置在程序的运行过程中都是固定不变的,仅当程序结束时才会被系统收回程中都是固定不变的,仅当程序结束时才会被系统收回。l 动态数据存储区:动态数据存储区:u栈(栈(stack)u堆(堆(heap) 它们是在程序运行过程中动态分配的,其大小将在程序运行过程它们是在程序运行过程中动态分配的,其大小将在程序运行过程动态地变化。动态地变化。典型的动态内存管理形式典型的动态内存管理形式:堆内存和栈内存的堆内存和栈内存的分配方向通常是分配方向通常是相向相向的的l栈内在从高地址向低地地址分配栈内在从高地址向低地地址分配l堆内存从低地址向高地址分配堆内存从低地址向高地址分配动态内存的存储结构动态内存的存

4、储结构l栈栈 使用使用线性存储的方式的方式l堆堆 使用使用链表来实现来实现C语言程序的存储区如图语言程序的存储区如图9-1所示。所示。9.1.2 C语言中的动态内存1.栈内存栈内存l栈是一种先入后出栈是一种先入后出FILO(后进先出后进先出LIFO)的内存区域。的内存区域。l栈内存由编译器管理栈内存由编译器管理l栈内存对应内存中的一块区域,有大小限制。栈内存对应内存中的一块区域,有大小限制。l栈内存的使用依赖于处理器的硬件机制栈指针寄存栈内存的使用依赖于处理器的硬件机制栈指针寄存器。器。l栈指针是一个指向栈内部区域的指针,它的值为一个地栈指针是一个指向栈内部区域的指针,它的值为一个地址,位于栈

5、内存的上、下界之间。址,位于栈内存的上、下界之间。l栈指针将栈区域分为两个部分栈指针将栈区域分为两个部分:u已使用区域已使用区域u未使用区域未使用区域栈内存的增长栈内存的增长(生长生长)方向:方向:l向上增长向上增长(生长生长)l向下增长向下增长(生长生长)栈指针的变化栈指针的变化l在向下增长的栈中,初始时栈指针是指向栈的上界在向下增长的栈中,初始时栈指针是指向栈的上界(高地址端),随着入栈数据的增加,栈指针将向(高地址端),随着入栈数据的增加,栈指针将向低地址端变化,即栈指针将变小。低地址端变化,即栈指针将变小。在向上增长的栈在向上增长的栈中则相反。中则相反。栈内存的重要特性:栈内存的重要特

6、性:后进先出(后进先出(LIFO)栈内存的基本操作:栈内存的基本操作:l入栈(入栈(PUSH)l出栈(出栈(POP)入栈、出栈过程(以向下增入栈、出栈过程(以向下增长的满栈为例)长的满栈为例)l入栈:先修改指针,再放内容入栈:先修改指针,再放内容,入栈后,指针指向刚入栈的,入栈后,指针指向刚入栈的数据数据l出栈:先取内容,再修改指针出栈:先取内容,再修改指针,指向下一个要出栈的数据,指向下一个要出栈的数据l只能对栈顶数据进行操作。只能对栈顶数据进行操作。栈内存是一端固定(栈底)栈内存是一端固定(栈底),一端浮动(栈顶)的。,一端浮动(栈顶)的。AABB低地址低地址高地址高地址上界上界下界下界X

7、X空栈和满栈空栈和满栈l空栈:空栈:栈指针所指的位置没有数据。入栈时,先放栈指针所指的位置没有数据。入栈时,先放数据,后修改指针,出栈时,先修改指针,再取数数据,后修改指针,出栈时,先修改指针,再取数据。据。l满栈:满栈:栈指针所指的位置总有数据(刚入栈的数据栈指针所指的位置总有数据(刚入栈的数据或将要取出的数据)或将要取出的数据)l一个系统是满栈一个系统是满栈 or 空栈是由处理器结构决定的,空栈是由处理器结构决定的,与程序的编写无关。与程序的编写无关。l前面演示的是满栈的情况前面演示的是满栈的情况栈总结:l 综合栈的生长方向和指针所指单元是否使用,栈可分为四种情综合栈的生长方向和指针所指单

8、元是否使用,栈可分为四种情况:况:u满递增栈:入栈时,指针先增加,再放数据,入栈后,栈:入栈时,指针先增加,再放数据,入栈后,栈指针指向刚入栈的数据;出栈时,先取数据,指针再减少,指针指向刚入栈的数据;出栈时,先取数据,指针再减少,出栈后栈指针指向下一数据。出栈后栈指针指向下一数据。u满递减栈:入栈时,指针先减小,再放数据,入栈后,栈:入栈时,指针先减小,再放数据,入栈后,栈指针指向刚入栈的数据;出栈时,先取数据,指针再增加,指针指向刚入栈的数据;出栈时,先取数据,指针再增加,出栈后栈指针指向下一数据。出栈后栈指针指向下一数据。u空递增栈:入栈时,先放数据,指针再增加,入栈后,栈:入栈时,先放

9、数据,指针再增加,入栈后,栈指针指向一个新的空位置;出栈时,指针先减少,再取数据指针指向一个新的空位置;出栈时,指针先减少,再取数据,出栈后栈指针指向的位置的数据已被取出(空位置)。,出栈后栈指针指向的位置的数据已被取出(空位置)。u空递减栈:入栈时,先放数据,指针再减小,入栈后,栈:入栈时,先放数据,指针再减小,入栈后,栈指针指向一个新的空位置;出栈时,指针先增加,再取数据指针指向一个新的空位置;出栈时,指针先增加,再取数据,出栈后栈指针指向的位置的数据已被取出(空位置)。,出栈后栈指针指向的位置的数据已被取出(空位置)。2.堆内存堆内存l在一般的编译系统中,在一般的编译系统中,堆内存的分配

10、方向和栈内存堆内存的分配方向和栈内存是相向的是相向的:如,栈内存从高地址向低地址增长时,:如,栈内存从高地址向低地址增长时,堆内存便从低地址向高地址分配。堆内存便从低地址向高地址分配。l在在C语言中,语言中,堆内存的分配和释放是通过程序调用堆内存的分配和释放是通过程序调用C语言的库函数语言的库函数(malloc()、calloc()、realloc())来来实现的。而栈内存是使用处理器的硬件机制实现的实现的。而栈内存是使用处理器的硬件机制实现的。堆内存的分配过程:堆内存的分配过程:l分配:每调用一次分配:每调用一次malloc()函数,都将返回一个当前函数,都将返回一个当前分配到的内存区域的首

11、地址(指针),根据指针可访分配到的内存区域的首地址(指针),根据指针可访问分配到的堆内存空间问分配到的堆内存空间l释放:调用释放:调用free()函数可释放用函数可释放用malloc()函数分配到的函数分配到的内存,不影响其他未释放的堆内存区域的使用。内存,不影响其他未释放的堆内存区域的使用。栈内存和堆内存在分配和使用上的区别:栈内存和堆内存在分配和使用上的区别:l栈内存只有一个入口点栈指针,它的位置是已使栈内存只有一个入口点栈指针,它的位置是已使用区和未使用区的界限,栈的访问只能通过栈指针及用区和未使用区的界限,栈的访问只能通过栈指针及偏移量进行偏移量进行l堆内存可有多个入口点,每次分配得到

12、的指针都是访堆内存可有多个入口点,每次分配得到的指针都是访问的入口点,每个指针指向的区域可被单独释放。问的入口点,每个指针指向的区域可被单独释放。堆内存的分配原则:堆内存的分配原则:l堆内存的分配是从堆内存的低地址端开始进堆内存的分配是从堆内存的低地址端开始进行分配,如果低地址端找不到一个满足要求行分配,如果低地址端找不到一个满足要求的连续区域,将到较高地址端去分配,直到的连续区域,将到较高地址端去分配,直到分配成功时返回分配的内存区域的首地址,分配成功时返回分配的内存区域的首地址,或失败时返回或失败时返回NULL。内存碎片内存碎片l频繁采用频繁采用malloc()和和free()函数进行不同

13、大小函数进行不同大小的内存分配和释放操作,将会在内存中产生的内存分配和释放操作,将会在内存中产生内存碎片内存碎片(太小而无法分配使用的内存区域(太小而无法分配使用的内存区域)。)。9.2 C程序中栈空间的使用9.2.1 参数使用栈空间参数使用栈空间 在在C语言程序中,栈空间是由编译器管理的,在程语言程序中,栈空间是由编译器管理的,在程序中体现序中体现栈空间使用的情况(用途)有栈空间使用的情况(用途)有:l使用栈空间进行函数参数传递使用栈空间进行函数参数传递u参数入栈的顺序:参数入栈的顺序:逆序逆序入入栈,栈,最右边的参数最右边的参数先入栈先入栈。l函数中的自动变量分配在栈空间中函数中的自动变量

14、分配在栈空间中l使用栈空间返回函数值使用栈空间返回函数值9.2.2 自动变量使用栈空间自动变量使用栈空间l函数参数和函数中的自动变量本质上是一致的,均函数参数和函数中的自动变量本质上是一致的,均被分配在栈空间中,均为局部变量。被分配在栈空间中,均为局部变量。l编译器在栈空间中函数参数的后面顺序为函数中的编译器在栈空间中函数参数的后面顺序为函数中的自动变量分配栈区域自动变量分配栈区域l函数中的静态变量被分配在静态存储区中。函数中的静态变量被分配在静态存储区中。9.2.3 程序中较大的栈程序中较大的栈l当函数的参数和局部变量为结构体类型当函数的参数和局部变量为结构体类型等构造数据类型时,它们仍被分

15、配到栈等构造数据类型时,它们仍被分配到栈空间中,但要占据更多的栈空间。空间中,但要占据更多的栈空间。l当参数为结构体类型时,通常采用结构当参数为结构体类型时,通常采用结构体类型的指针作为函数参数,以节约存体类型的指针作为函数参数,以节约存储空间和提高程序运行效率。储空间和提高程序运行效率。9.2.4 栈空间的特性栈空间的特性l栈空间的使用完全由编译器管理,在程序中栈空间的使用完全由编译器管理,在程序中不需要管理栈。不需要管理栈。l函数返回后,函数中在栈上的内容将被释放函数返回后,函数中在栈上的内容将被释放,所以,函数调用结束后,函数中的形参和,所以,函数调用结束后,函数中的形参和自动变量均不能

16、被别的函数访问自动变量均不能被别的函数访问。l函数不能返回自动变量的指针(地址)函数不能返回自动变量的指针(地址),但,但可以将自动变量的指针作为参数传递给其他可以将自动变量的指针作为参数传递给其他函数。函数。9.3 C程序中的堆空间使用9.3.1 分配和释放堆内存的库函数分配和释放堆内存的库函数l堆内存区域的分配和释放是通过调用库函数堆内存区域的分配和释放是通过调用库函数来完成的,这些库函数对应的头文件:来完成的,这些库函数对应的头文件:stdlib.h或malloc.hl实现堆内存分配和释放的实现堆内存分配和释放的C函数主要有函数主要有4个个:uvoid * malloc(size_t s

17、ize);uvoid free(void * ptr);uvoid * calloc(size_t nmemb,size_t size);uvoid * realloc(void * ptr,size_t size);malloc函数l函数原型:void * malloc(size_t size);l参数:size请求分配的内存大小(字节数)。l作用:在堆中分配一个长度为size的连续空间。l返回值:分配成功,返回一个指向分配区域的起始地址(指针)。如内存空间不足,返回空指针NULL。 (此处:void为无确定类型) calloc函数l函数原型:void * calloc(size_t nme

18、mb,size_t size);l参数:nmemb需要分配的块数,size每块字节数l作用:在堆中分配nmemb个长度为size的连续空间(nmemb*size)。l返回值:分配成功,指向分配区域起始地址(指针),若分配不成功,返回NULL值。l与malloc()的区别:calloc()将把分配到的内存区域全部初始化为0。而malloc()不对分配到的内存区域进行初始化。realloc函数l函数原型:void * realloc(void *ptr,size_t size);l参数:ptr需要重新分配堆内存的指针,size重新分配的内存大小(字节数)。l作用:将ptr指向的内存区域更改为siz

19、e个字节。l返回值:分配成功,指向重新分配的区域的起始地址(指针),若分配不成功,返回NULL值。l注意:uPtr应是由应是由calloc或malloc或realloc分配的内存区域指针u重新分配后的内存区域中的前面部分的内容与重新分配前内存区域的前面部分的内容相同。u如果ptrNULL,此函数等价于malloc(size);如果size0,此函数的作用等价于free(ptr)。free函数l函数原型:void free(void *ptr);l参数:指向待释放区域的指针,它指向的是最近一次calloc或malloc或realloc分配的存储区域。l作用:释放由ptr指向的内存区,使这部分内存

20、区能被分配给其他程序使用。l返回值:无返回值。 9.3.2 库函数使用malloc()和free()l以上四个函数中,使用最多的是以上四个函数中,使用最多的是malloc()和和free()两两个函数。个函数。lmalloc()函数分配成功后返回的是函数分配成功后返回的是void*形式的指针形式的指针,可以根据需要转换成任何类型的指针。,可以根据需要转换成任何类型的指针。lfree()函数的参数类型是函数的参数类型是void * 形式的指针,可以接形式的指针,可以接受任何类型的指针,但一定受任何类型的指针,但一定要要是动态分配函数返回是动态分配函数返回的指针。的指针。l在使用在使用malloc

21、()时,经常使用表达式时,经常使用表达式sizeof(XXX)或或n*sizeof(XXX)形式的参数,其中形式的参数,其中XXX为某种类型标为某种类型标识符(包括结构体类型)识符(包括结构体类型)l在访问分配到的内存空间前,应该判断返回在访问分配到的内存空间前,应该判断返回的指针是否为的指针是否为NULL,以判断分配是否成功,以判断分配是否成功。l在使用结束后,应该使用在使用结束后,应该使用free()释放。释放释放。释放后将由系统收回,以便下次分配时使用。后将由系统收回,以便下次分配时使用。l使用使用free(ptr)释放释放ptr指向的内存空间后,指向的内存空间后,ptr指针仍指向原内存

22、区域,但不能访问它指针仍指向原内存区域,但不能访问它所指向的内存区域。因此,释放后应对所指向的内存区域。因此,释放后应对ptr赋值为赋值为NULL。calloc()l与与malloc()有两个区别:有两个区别:ucalloc()将分配到的内在空间初始化为将分配到的内在空间初始化为0ucalloc()有两个参数有两个参数l如:如:ucalloc(sizeof(long),10)u与与malloc(sizeof(long)*10)等价等价realloc()lrealloc()实际有三种功能实际有三种功能u当指针为当指针为NULL时,与时,与malloc()作用几乎相同作用几乎相同u当当size为为

23、0时,与时,与free()作用相同,释放指针所指的内存空作用相同,释放指针所指的内存空间间u当指针和不为当指针和不为NULL和和size不为不为0时,将根据指针指向的堆时,将根据指针指向的堆内存区域的情况和指定大小重新分配内存。内存区域的情况和指定大小重新分配内存。lrealloc()重新分配内存时,有三种可能性:重新分配内存时,有三种可能性:u缩小内存:指针位置不变缩小内存:指针位置不变u扩大内存:指针位置不变,扩大内存:指针位置不变,u扩大内存:指针位置需要改变,并释放原内存区域扩大内存:指针位置需要改变,并释放原内存区域l扩大内存时,若指针位置发生了改变,还需将原区扩大内存时,若指针位置

24、发生了改变,还需将原区域中的内容复制到新分配内存区域的前面部分。域中的内容复制到新分配内存区域的前面部分。9.3.3 堆内存的特性合理使用堆内存,可为程序开发带来很大的方合理使用堆内存,可为程序开发带来很大的方便性和灵活性便性和灵活性堆内存使用不当,容易出现以下几个问题:堆内存使用不当,容易出现以下几个问题:l如果开辟的内存没有释放,会造成内存泄漏如果开辟的内存没有释放,会造成内存泄漏l可能出现野指针被使用或释放可能出现野指针被使用或释放l非法释放指针非法释放指针内存泄漏内存泄漏l简单地说,就是申请了一块内存空间,使用完毕后简单地说,就是申请了一块内存空间,使用完毕后没有释放掉。没有释放掉。l

25、它的一般表现方式是程序运行时间越长,占用内存它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,致使系统性能降低甚至越多,最终用尽全部内存,致使系统性能降低甚至整个整个系统崩溃。系统崩溃。导致内存泄漏常见的三种情况:导致内存泄漏常见的三种情况:l由程序申请的一块内存后,没释放便对该指针重新由程序申请的一块内存后,没释放便对该指针重新赋值,导致没有任何一个指针指向它,那么这块内赋值,导致没有任何一个指针指向它,那么这块内存就泄露了。如:存就泄露了。如: int ptr=(int *)malloc(20); ptr=(int *)malloc(10);l将动态分配的内存指针作为函数

26、参数传递给其他函将动态分配的内存指针作为函数参数传递给其他函数,在函数中和返回后均未对其进行释放。数,在函数中和返回后均未对其进行释放。l在函数在进行动态内存分配并将其地址赋值给函数在函数在进行动态内存分配并将其地址赋值给函数内的动态指针变量内的动态指针变量,且未调用,且未调用free()函数释放函数释放。 内存泄漏的几种情况内存泄漏的几种情况l (1). 常发性内存泄漏。 发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。致一块内存泄漏。 l (2). 偶发性内存泄漏。 发生内存泄漏的代码只有在某些特定环境或操作过

27、程下才会发生发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。重要。 l (3). 一次性内存泄漏。 发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在主函数中分,导致总会有一块仅且一块内存发生泄漏。比如,在主函数中分配内存,在所有函数中都没有释放该内存,所以

28、内存泄漏只会发配内存,在所有函数中都没有释放该内存,所以内存泄漏只会发生一次。生一次。 (4). 隐式内存泄漏。 程序在运行过程中不停的分配内存,但是直到结束的时候才释程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存

29、泄漏。有内存。所以,我们称这类内存泄漏为隐式内存泄漏。 野指针野指针l野指针:野指针:指向不可用内存区域的指针,而不是指向不可用内存区域的指针,而不是NULL指指针针l对这种指针进行操作的话,将会使程序发生不可预知的对这种指针进行操作的话,将会使程序发生不可预知的错误。错误。 l人们一般不会错用人们一般不会错用NULL指针,但是指针,但是“野指针野指针”是很危险是很危险的。的。l野指针的成因:野指针的成因: u一、指针变量没有被初始化。任何指针变量刚被创建时它的缺省一、指针变量没有被初始化。任何指针变量刚被创建时它的缺省值是随机的。所以,指针变量在创建的同时应当被初始化,要么值是随机的。所以,

30、指针变量在创建的同时应当被初始化,要么将指针设置为将指针设置为NULL,要么让它指向合法的内存。,要么让它指向合法的内存。 u二、指针二、指针p被被free或者或者delete之后,并没有置为之后,并没有置为NULL,让人误以,让人误以为为p是个合法的指针。是个合法的指针。u函数返回指向自动变量或形参变量的指针。函数返回指向自动变量或形参变量的指针。非法释放指针非法释放指针l用用free()函数释放不是由函数释放不是由malloc()、calloc()、realloc()函数返回的指针所指向的内存空间。函数返回的指针所指向的内存空间。l对已经被对已经被free()函数释放了的指针再次进行释放,

31、即函数释放了的指针再次进行释放,即多次释放同一指针。多次释放同一指针。通过库函数管理堆内存时应注意的问题:通过库函数管理堆内存时应注意的问题:l调用调用malloc()、calloc()、realloc()函数后,应判断函数后,应判断返回的指针是否为返回的指针是否为NULL,以判断分配是否成功,以判断分配是否成功。l每次通过指针访问堆内存空间时应先判断指针是每次通过指针访问堆内存空间时应先判断指针是否为否为NULL。l使用完堆内存后必须用使用完堆内存后必须用free()函数进行释放,以防函数进行释放,以防止内存泄漏。止内存泄漏。l使用使用free()函数释放后应将该指针置为函数释放后应将该指针

32、置为NULL。,。,以避免野指针被使用以避免野指针被使用l为防止多次释放同一指针,释放前也应判断指针为防止多次释放同一指针,释放前也应判断指针是否为是否为NULL。l尽量做到尽量做到“谁申请,谁释放谁申请,谁释放”。9.4 堆内存和栈内存使用的比较9.4.1 利用返回值传递信息利用返回值传递信息l函数中通过函数中通过return 向主调函数返回值。向主调函数返回值。l函数的返回值是通过栈实现的。函数的返回值是通过栈实现的。l函数的返回值可以是函数的返回值可以是int、char等基本数据类型,也可等基本数据类型,也可以是结构体类型,还可以是指针类型。以是结构体类型,还可以是指针类型。l当函数返回

33、值是指针时,这个指针当函数返回值是指针时,这个指针不能是被调函数中不能是被调函数中的自动变量、形式参数的地址的自动变量、形式参数的地址,但可以指向被调函数,但可以指向被调函数内的内的static变量、堆内存及主调函数栈上的内存。变量、堆内存及主调函数栈上的内存。l当函数返回值为被调函数中动态分配的堆内存指针时当函数返回值为被调函数中动态分配的堆内存指针时,需要在外部进行释放,否则会造成内存泄漏。,需要在外部进行释放,否则会造成内存泄漏。lC库函数中,返回指针值的函数最典型的有内存处理库函数中,返回指针值的函数最典型的有内存处理函数和字符处理函数函数和字符处理函数返回静态内存地址时,可以是返回静

34、态内存地址时,可以是l全局的静态变量的地址全局的静态变量的地址l函数内部的局部静态变量的地址函数内部的局部静态变量的地址返回被调函数中的局部变量(含形式参数)的地址返回被调函数中的局部变量(含形式参数)的地址,将会造成野指针。,将会造成野指针。当需要返回函数内部栈上的内容时,不能使用指针当需要返回函数内部栈上的内容时,不能使用指针,返回非指针即可,此时将进行值拷贝,返回结构,返回非指针即可,此时将进行值拷贝,返回结构体类型时也一样(体类型时也一样(P225) 。所以返回结构体类型数。所以返回结构体类型数据时系统开销较大。但通过返回结构体类型数据可据时系统开销较大。但通过返回结构体类型数据可以返回多个不同类型的值(分别放在结构体类型的以返回多个不同类型的值(分别放在结构体类型的不同成员中)不同成员中) 。9.4.2 利用参数传递信息实参和形参的信息传递均是传值(包括指针参实参和形参的信息传递均是传值(包括指针参数和结构体类型参数)数和结构体类型参数)数组名作为实参时,形参可定义为数组,也可数组名作为实参时,形参可定义为数组,也可以定义为指针,但编译器都将其处理成指针。以定义为指针,但编译器都将其处理成指针。当参数为指针变量时,形参变量接受实参变量当参数为指针变量时,形参变量接受实参变量的值,使得形参变量与实参变量均指向同一位的值,使得形参变量与实参变量均

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论