理解內存與指針

內存與內存地址

什麼是內存


內存是計算機中重要的部件之一,它是與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。

前端小然子的博客

相關文章
相關標籤/搜索