查看原文
其他

NDK探究之旅《五》——指针和数组之间的关系

2017-05-11 于亚豪 终端研发部

前言介绍

指针和数组之间的关系

于亚豪的博客地址

正文


NDK探究之旅《一》——对jni和NDK的认识

NDK探究之旅《二》——C语言的基本认识

NDK探究之旅《三》—C语言的输入输出函数

NDK探究之旅《四》——指针的强化理解

指针和数组之间的关系

  • 数组名就是数组第一位的地址。即数组名是元素的首地址。

  • 数组就是一块连续的内存空间,每个元素之间的距离和元素的类型有关

  • 数组名取地址得到的还是元素的首地址

  • 另一种方式的输出值arry[i] = *(arry+i)

示例代码:

打印结果:

关于指针的运算

  • 指针的运存实际上指的是内存地址的运算。

由于指针就是一块内存空间的地址,只能用来操作连续的内存空间。

#include main(){      
       int array[] = {1,2,4,5,6,9,12,34,45,78,90,124}; n       //printf("array[0]=%dn",array[0]);n        printf("array[0]=%dn",*(array+1));n    tsystem("pause");n}

静态内存和动态内存

动态内存

  • 程序员在 new 一个对象的时候就是 申请了一块动态内存

在我们执行一个new 一个对象后,都存放在堆存中,在Java语言中,Java有自己的垃圾回收机制 ,回收的是对内存。 而在C语言中不会被系统自动回收。

  • 静态内存 比如说在方法体中,int i= 0;

普及

栈内存和对内存

  • 占内存

    • 一块连续的内存空间

    • 为编译器自动分配和释放,如函数参数,局部变量,临时变量

    • 由操作系统自动回收

  • 对内存

    • 不连续存储空间

    • 可以可以占据整个空间

    • 典型的例子:程序员new 的对象都可在对内存中。

    • 由垃圾回收器回收

栈内存和堆内存的区别

1.程序的内存分配

  • 栈(stack):有编译器自动分配和释放,存放函数的参数、局部变量、临时变量、函数返回地址等;

  • 堆(heap):一般有程序员分配和释放,如果没有手动释放,在程序结束时可能由操作系统自动释放(?这个可能针对Java那样的有回收机制的语言而说的,对于c/c++,这样的必须要手动释放开辟的堆内存),稍有不慎会引起内存泄漏。

2.申请后系统的响应

  • 栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出。

  • 堆:在记录空闲内存地址的链表中寻找一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统会在这块内存空间的首地址出记录本次分配空间的大小,这样代码中的delete 才能正确释放本内存空间。系统会将多余的那部分重新空闲链表中。

3、申请大小限制

  • 栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

  • 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

4、分配效率

  • 栈:由系统自动分配,速度较快。但程序员是无法控制的。

  • 堆:由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

    • 另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活

5、存储内容

  • 栈:在栈中,第一个进栈的是主函数下一条指令的地址,然后是函数的各个参数,在大多数编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意,静态变量不入栈。出栈则刚好顺序相反。

  • 堆:一般在堆的头部用一个字节存放堆的大小,具体内容由程序员安排。

根据《C内存管理技术内幕》一书,在C中,内存分成5个区,他们分别是堆,栈,自由存续区,全局/静态存续区,常量存续区。

  • 栈:内存由编译器在需要时自动分配和释放。通常用来存储局部变量和函数参数。(为运行函数而分配的局部变量、函数参数、返回地址等存放在栈区)。栈运算分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  • 堆:内存使用new进行分配,使用delete或delete[]释放。如果未能对内存进行正确的释放,会造成内存泄漏。但在程序结束时,会由操作系统自动回收。

  • 自由存储区:使用malloc进行分配,使用free进行回收。和堆类似。

  • 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。(全局变量、静态数据、常量存放在全局数据区)

  • 常量存储区:存储常量,不允许被修改。


这里,在一些资料中是这样定义C++内存分配的,可编程内存在基本上分为这样的几大部分:

  • 静态存储区

  • 堆区

  • 栈区。

他们的功能不同,对他们使用方式也就不同。

  • 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

  • 栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  • 堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或 delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

博客地址:




让心,在阳光下学会舞蹈

让灵魂,在痛苦中学会微笑

—终端研发部—



如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809   

微信公众号:终端研发部

(欢迎关注学习和交流)



            

Hello,伙伴们

长按二维码就可以关注我们啦



(欢迎关注学习和交流)



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存