理解内存与指针

内存与内存地址

什么是内存


内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中全部程序的运行都是在内存中进行的,所以内存的性能对计算机的影响很是大。javascript

内存也被称为 内储存器 和 主存储器,其做用是用于暂时存放CPU中的运算数据,以及和硬盘等外部存储器交换的数据。下面是CPU的组成和工做原理:html

图一

在计算机的组成结构中,有一个很重要的部分是储存器。前端

存储器是用来存储程序和数据的部件,对于计算机来讲,有了存储器,才有记忆功能,才能保证正常工做。存储器的种类不少,按其用途可分为主存储器和辅助存储器,主存储器又称内存储器(简称内存)。java

内存就是暂时存储程序以及数据的地方,相对于外存(硬盘是外存的一种)而言,咱们在电脑上输入文字、字符的时候,它就会被存入内存中,只有当你选择保存文件的时候,内存中的数据才会被存入硬盘。算法

内存是CPU可以直接寻址的存储空间,特色是存取速率特别快,临时存放数据,不能永久保存数据。数据结构

外存是计算机的存储器的一种,主要用来存放暂时不用的程序和数据。特定是容量大、价格低,可是存取速度慢。外存和内存之间尝尝频繁的交换信息。数据结构和算法

什么是内存地址


内存地址是用于软硬件等不一样层级中的数据概念,用来访问内存中的数据。ide

能够经过WiKi或者百度百科进行更加深刻的了解。函数

指针、地址与引用

引用


引用是一个变量的别名,为何引入别名?是由于咱们想定义一个变量,由这个变量来共享另外一个变量的内存空间,因此使用别名是一个很好的选择。性能

变量是什么? 是一个内存空间的名字,若是咱们给这个内存空间再另外起一个名字,就是能共享这个内存了,引用(别名)由此而来。

好比:

var obj = { a: 1, b: 2 };
var obj1 = obj;
复制代码

这里咱们就能够说变量obj1是变量obj的一个引用;(由于在javascript中,object类型的赋值,是引用地址赋值)

指针


指针,指向另外一个内存空间的变量,咱们能够用个它来索引另外一个内存空间中的内容,而指针自己有本身的内存空间。

以下图所示:

图二

二者区别


引用是一个变量的别名,自己不单独分配本身的内存空间,而指针有本身的内存空间。

引用在开始的时候就绑定到了一个内存空间(开始必须赋初值), 因此它只能是这个内存空间的名字, 而不能改为其余的, 固然, 咱们能够改变这个内存空间的值。

eg:

var obj = { a: 1, b: 2 };
var obj1 = obj;

obj.b = 3;
// {a: 1, b: 3 }

obj1.a = 4;
// {a: 4, b: 3 }

obj1 = { a:1, c:2 };
console.log(obj1);
// { a:1, c:2 };
console.log(obj);
// {a: 4, b: 3 }
复制代码

这段代码的过程以下:

图三

指向变量的指针

一个变量的地址指出了变量的存储单元在内存中的具体位置,能对变量进行存取操做。那这个变量就是指向变量的指针。

能够参考上面的 “图二” 能够很好的理解指向变量的指针。

指向指针的指针

若是一个指针变量存放的又是另外一个指针变量的地址,则称这个变量为指向指针的指针变量或指向指针的指针。

#include <stdio.h>

// 入口主函数
void main () {
    int a = 5;
    // 这里&a就是变量a的内存地址
    int *p = &a;
    // 这里是打印输出变量a的值
    printf("%d\n", *p);
}
复制代码

指向函数的指针

指向函数的指针变量被称为函数指针。自己是指针变量,只不过该指针变量指向函数。

有了函数指针以后,就能够用该指针变量来调用函数。

函数指针有两个用途:

  • 调用函数

  • 作函数的参数

// 调用函数
function max (x, y) {
    return x > y ? x : y;
}

max(1, 2);


// 作函数的参数
const a = [1,5,3,4,78,96,54,1,2,3,4];

function sum(total, num) {
    return total + Math.round(num);
}

a.reduce(sum);

复制代码

以上例子中 maxsum 都是指向函数的指针变量。

多级指针

多级指针,是指 “指向地址的指针”;

一级指针


#include <stdio.h>

// 入口主函数
void main () {
    int i = 10;
    // 这里&a就是变量a的内存地址
    int *p1 = &a;
    // 这里是打印输出变量a的值
    printf("%d\n", *p1);
}
复制代码

在这里的 *p1 就是一级指针

这里一样参考 “图二” 来理解

指针变量p能够经过 *p1 来获取到变量i的值,也能够进行修改操做,总之 *p1 能够操做变量i的内存空间,因此 * 是一个操做内存空间的一个符号。

*p也就被称为一级指针。

二级指针


同上面讲的一级指针原理一致。

#include <stdio.h>

// 入口主函数
void main () {
    int i = 10;
    // 这里&a就是变量a的内存地址
    int *p1 = &a;
    int **p2 = &p1;
}
复制代码

**p2 即为二级指针。


其他多级指针依旧同理:

int ***p3 = &p2;
int ****p4 = &p3;
复制代码

动态内存分配

内存 描述 特性
栈区 是一个肯定的常数(1~2M) 不一样平台会有不一样大小,超出会提示stackoverflow 自动分配 , 自动释放
堆区 用于动态内存分配 手动分配和释放 , 可占用80%内存
全局区或静态区 在程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量) 只初始化一次
程序代码区 代码区指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每一个进程),若是反复,则须要使用跳转指令,若是进行递归,则须要借助栈来实现。 代码区的指令中包括操做码和要操做的对象(或对象地址引用)

理解指针的操做,更加有助于咱们更快的理解数据结构和算法。

原文地址: 理解内存与指针

致谢

感谢你们阅读个人文章,若是对我感兴趣能够关注个人博客,有时间的能够去博客点击页面右上角帮我点个star。

前端小然子的博客

相关文章
相关标签/搜索