成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

指針是怎樣一步步發明出來的?

開發 前端
有了變量,程序員在編程時就可以操作符號num而不是0x8049320了,但只使用符號num也會有問題,這個問題就是如果兩個函數需要共享內存中的一份數據該怎么辦呢?

大家好,我是小風哥,今天來聊聊指針是怎么被一步步被發明出來的。

內存本身就是一個裝字節的容器,和你用的鞋柜、書柜等沒有本質區別:

圖片圖片

唯一的區別在于鞋子或者書可以隨便放,無非找的時候困難點。

但字節就不一樣了,不能隨便放,必須明確放到了哪里,因此內存中的每個裝字節的地方都得編號,這個編號就是內存地址。

圖片圖片

在這種情況下,該怎么向內存中寫數據呢?很簡單,就一句話:

把數字2寫到第0x8049320號內存中

這就是所謂的內存讀,用機器指令表示可以這樣:

store 0x8049320 2

效果是這樣的:

圖片圖片

可以看到,利用store指令你可以直接操作任何一個內存地址,也就是直接操作或者控制內存這種硬件,這是一種很強大的能力:

圖片圖片

但同時也非常危險,如果內存地址算錯那么寫到內存中的數據就是錯誤的或者會用錯誤的數據覆蓋掉內存中原本的數據:

圖片圖片

而且這也很繁瑣,因為程序員需要直面內存,看下內存地址0x8049320,你的第一反應肯定是:這是個啥?

圖片圖片

人類天生不擅長應對數字,而是更喜歡代號:張三李四。

顯然,"把num賦值為2"要比"store 0x8049320 2"要容易理解很多,這里num這個代號就是所謂編程語言中的變量。

圖片圖片

就這樣變量誕生了。

實際上變量不過是某個內存格子的一個代號:

圖片圖片

當然這是在編程語言層面的理解,在真實的內存中可不存在一個叫做num的符號,而是內存地址0x8049320這個地方保存了數字2:

圖片圖片

編譯器不過是把代號num和0x8049320這塊內存關聯起來。

有了變量,程序員在編程時就可以操作符號num而不是0x8049320了,但只使用符號num也會有問題,這個問題就是如果兩個函數需要共享內存中的一份數據該怎么辦呢?

圖片圖片

以C語言為例,現在有兩個函數都需要對變量num執行加1操作:

void func1(int a) {
  a = a + 1;
}
void func2(int b) {
  b = b + 1;
}


int num = 2;
func1(num);
func2(num);

我們期待的效果是func1和func2執行完畢后num的值變成4,但實際上兩個函數執行完畢后num的值依然是2。

為什么呢?

我們希望的是a和num代表同一個內存格子:

圖片圖片

但實際上變量a上有獨屬于自己的內存格子:注意看函數的參數int a,

圖片圖片

調用函數傳遞參數func1(num)后的效果是這樣的:

圖片圖片

func函數操作的根本就是和num完全不同的另一個變量,它們位于不同的內存格子(內存地址)。

既然聲明變量時沒有辦法直接關聯到某塊內存那么我們就必須用間接的辦法,因為計算機科學中任何問題都可以通過增加一個中間層來解決。

圖片圖片

這個中間層就是借助內存地址。

圖片圖片

不要忘了除了2關聯到了符號num,這當然只是邏輯上存在的關聯,編譯器給實現的;

實際上2還有一個真實的、物理的上的屬性,那就是內存地址,這是真實的存在,不以任何上層封裝為轉移;

圖片圖片

既然變量a沒辦法直接關聯到num,那就曲線救國,變量a保存2所在的內存地址,也就是變量num的內存地址:

圖片圖片

變量a依然是那個變量a,但此時變量a中保存的不再是2這個數字,而是另一個數字0x8049320。

然而此時如果你這樣寫:

int b = a;

此時b中保存的依然是0x8049320這個數字,而不是2這個數字:

圖片圖片

顯然必須明確的告訴編譯器我們希望把變量a的內容當做內存地址來使用而不是單純的數字。

怎么做到呢?在聲明變量和使用變量時加個符號就好:

int a;      ---->  int* a;
int b = a;  ---->  int b = *a;

就這樣指針被發明了出來,現在的變量a就是所謂的指針,變量a關聯的內存保存的依然是個普通的數字,只不過這個數字可以被當做內存地址使用。

再次強調,當我們寫下int* a時,變量a依然會占據一塊內存格子:

圖片圖片

這塊內存中可以裝入任何的數字,這個數字代表的另一塊內存的起始地址:

圖片圖片

所以并不是說變量a直接指向一塊內存或者指向num:

圖片圖片

變量a和變量num沒有半毛錢關系,變量a和變量num位于不同的內存地址上,只不過變量a的內容比較特殊而已,它恰好是變量num所在的內存地址:

圖片圖片

所以從這里看我們只能說a間接指向了變量num。

當然在你熟悉指針的概念后就可以放心的忽略這層間接了,可以把a看做直接指向變量num,這就是我們常說的指針指向哪里。

圖片圖片

在很多情況下,我們實際上根本就不關心內存地址這種間接層,可以直接把a看做num的另一個稱謂,這在其它高級語言中叫做引用

所以引用實際上是在指針基礎上的進一步抽象,使用引用時我們可以簡單的把a和num等同看待:

圖片圖片

此時a和num都表示0x8049320這塊內存中的內容,也就是數字2。

C語言中的指針把內存地址暴露給了程序員,這給了程序員直接控制硬件的能力,這種能力十分的powerful,因此C很適合進行系統編程,可以用來實現操作系統等;

圖片圖片

但也非常危險,內存地址計算錯誤的話會導致程序崩潰或者出現難以排查的bug。

圖片圖片

但并不是所有程序員都要像Linus那樣去編寫操作系統,如果你只想實現一些應用層面的程序,爬蟲等,在這種情況下指針就不是必須的,所以很多編程語言并不提供指針。

指針的出現讓高級語言也可以操作復雜的數據結構比如鏈表和二叉樹等。

圖片圖片

1964年Harold Lawson因在PL/I中發明指針這一概念而榮獲2000年IEEE計算機先鋒獎,獲獎理由是“指針概念的引入首次使高級語言靈活處理鏈表成為可能”。

責任編輯:武曉燕 來源: 碼農的荒島求生
相關推薦

2024-06-27 08:30:36

內存擴容堆區

2025-04-03 01:45:00

2025-03-28 09:39:15

CPU指令信號

2025-04-30 04:20:00

操作系統虛擬內存

2024-11-11 10:28:33

操作系統Unix系統

2024-08-30 08:30:29

CPU操作系統寄存器

2017-01-19 21:08:33

iOS路由構建

2018-07-13 15:36:52

2024-08-06 09:29:54

程序機器指令字符串

2025-04-09 08:45:00

操作系統進程線程

2018-12-24 10:04:06

Docker存儲驅動

2019-03-05 14:09:27

Docker存儲容器

2019-07-09 15:23:22

Docker存儲驅動

2021-03-15 09:20:15

微軟IBM研究院

2016-11-02 18:54:01

javascript

2017-12-25 11:50:57

LinuxArch Linux

2010-03-04 16:28:17

Android核心代碼

2011-05-10 10:28:55

2018-04-23 14:23:12

2018-06-11 15:30:12

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩二区 | 日韩欧美专区 | 亚洲欧美一区二区三区国产精品 | 欧美综合视频 | 日本午夜视频 | 黄色片在线观看网址 | 成人在线 | 在线欧美日韩 | 久久久久久久av | 一级毛片视频 | 亚洲精品永久免费 | 一区二区三区在线播放 | 国产91 在线播放 | 国产欧美日韩精品一区二区三区 | 欧美日韩不卡合集视频 | 日韩午夜网站 | 亚洲国产视频一区 | 国产高清在线精品一区二区三区 | 日韩一区精品 | 日韩欧美中文字幕在线观看 | 国产一区二区 | 中文在线a在线 | 美女久久视频 | 欧美日韩电影免费观看 | 国产农村妇女精品一区 | 粉嫩一区二区三区国产精品 | 精品视频一区二区在线观看 | 久久夜视频| 日韩欧美久久 | 欧美精品一区二区三区在线四季 | 日韩无| 91精品久久久久久久久久入口 | 美女视频三区 | 久久久精品一区 | 97精品国产 | 81精品国产乱码久久久久久 | 国产精品视频久久久 | 亚洲日本欧美日韩高观看 | 最新中文字幕在线 | 午夜影院在线观看 | 免费看黄色片 |