在c中當定義一個變數並對其取地址的時候電腦發生了什麼?

初學c,看到指針。有取地址符

其原理是找到「每一個變數標識符在編譯期間,編譯器會為它們創建一個符號表,其中存放著變數標識符相應的各種屬性,如類型、地址標識等」(是這樣嗎?)中的地址。

1:這些符號表數據又是存在哪裡的呢?--&>每創建一個變數就要創建一個符號表的話不是要佔據很大的存儲空間?--&>電腦到底能創建多少個變數?

2:電腦是如何從這麼多變數中找到某個變數的?--&>有這麼多變數 電腦在找的時候是挨個遍歷所有的變數名以找到某個變數嗎?--&>那所有的變數名都在某個表中?


0:我覺得你才剛剛學編程這些問題肯定是搞不明白的,所以我也只能簡單的跟你講一下。

1:符號表是編譯的時候用的,編譯完了就扔掉了。當然如果是Visual C++的話,會順便保存在pdb文件裡面,以供調試使用。可以創建多少個變數基本上跟你的硬碟大小有關係。

2:怎麼找變數這個問題就複雜了。在正常情況下,我們使用RSP和RBP兩個寄存器來追蹤堆棧。你每次調用一個函數的時候RSP和RBP就會被修改,退出一個函數的時候RSP和RBP就會被恢復成之前的值。所有的變數最終都會被編譯成一個數字,代表跟其中一個寄存器的距離,這同時也解釋了為什麼遞歸的時候同一個函數的變數不會相互影響。還有很多其他情況,我就不講了。

倘若你一定要搞清楚,就去學x64彙編,什麼都自己來,什麼都明白了。


通俗來講,這個是編譯器乾的

符號表在編譯期間由編譯器生成,你說這個是標識符號表,目的是為了生成文件的時候用來替換地址和語法分析什麼的,假設變數xiao的地址是0x19450815,變數jing的地址是0x19450909,最終生成文件的時候xiao都會被替換成0x19450815,jing都會被替換成0x19450909。生成的代碼中不會有符號、符號表(僅限C語言)。編譯過程中是存在內存中,你太小看內存了,你一個變數名能有多長?你能取多少變數名?。。。

編譯器在編譯一個程序的時候生成符號表,遍歷肯定是不用的,你以後學了數據結構就知道用hashtable只要O(1)的時間就可以進行查找插入,list、hashtable、binary tree,這三個是基礎數據結構,涵蓋絕大部分計算機常見問題的解決方案。

vczh說的SP BP寄存器是程序運行過程中的行為,程序是一段根據cpu行為精心拼湊的數字,所以cpu可以執行這段數字,其實cpu啥也不知道,它只是不斷地解釋這些數字而已,本來你要自己拼湊這些數字,但是編譯器和高級語言幫你幹了這件事。cpu的物理原理屬於計算機體系結構,工作原理得看cpu廠商手冊(也就是彙編語言了,有本書叫《csapp》,就是講這個工作原理的)

求知慾旺盛是好事,但以後不懂的東西更多,你根本不需要立馬知道答案,你只需要記下來以後自然就學到了。

cs知識是網狀的,你多學才能聯繫起來。


總結一下上面的回答,簡單說就是這個問題暫時不用深究,以後去看一下微機原理就明白了。

拿我個人來說,高一接觸的C++,大三才學微機原理,一點都不影響我中間5年寫程序。


不要一開始學編程語言就陷入細枝末節中!


這個涉及編譯、鏈接、載入多個步驟哦,如前面其他人所述,初學不要太糾結於這些。

給個建議:學習C的話適當了解一下彙編,對你加深對C語言本身的理解很有幫助


1:這些符號表數據又是存在哪裡的呢?--&>每創建一個變數就要創建一個符號表的話不是要佔據很大的存儲空間?--&>電腦到底能創建多少個變數?

不考慮動態載入和動態庫的情況,最終的程序不包含符號表。所有符號都已經轉換成了相對/絕對地址。

2:電腦是如何從這麼多變數中找到某個變數的?--&>有這麼多變數 電腦在找的時候是挨個遍歷所有的變數名以找到某個變數嗎?--&>那所有的變數名都在某個表中?

不找,因為根本沒有符號,都是現成的立即數。


程序運行的時候是不知道所謂變數名等標誌符的,變數名只存活於編譯、鏈接期間。

CPU有幾個寄存器可以保存數據。

32位CPU每個寄存器大小32位也就是4位元組,64位CPU是8位元組。變數分配時,CPU就會把變數所在的地址載入到某個寄存器之中,當它需要這個變數時就會直接從當初保存他的寄存器中讀出地址來,再去這個地址讀取變數的值。

所謂「變數分配」,說的不嚴謹一些就是在內存中開闢一塊空間保存數據。在C的語境里內存空間分了兩大類,堆(heap)和(棧)。

棧中的空間不需要你參與管理、分配,操作系統載入你的程序時會為你準備好了一大塊內存作為棧空間。你在函數里的各種變數定義就是直接進入棧里那塊內存了。比如本地變數這麼定義:

int a = 123; //這可能就表示命令CPU在棧+8處保存一個4位元組整數123

CPU有兩個特殊的寄存器,32位的叫ebp、esp,64位叫rbp、rsp,用於跟棧有關的一切操作中。你的程序運行時CPU就已經把棧空間起始地址保存到這倆寄存器里了,此後但凡遇到需要讀取棧里某塊內存的情況,CPU都會直接從esp、ebp或rsp、rbp里得到棧的地址,然後從里讀取數據。比如要讀取變數a,CPU就用esp+8作為a的地址,直接從中讀出數據。

從堆里分配空間需要你顯式的調用內存分配函數比如malloc。與題目關係不大暫且不表。

理論上你的可以定義無數變數,只要內存空間足夠。

很多細節描述的並不準確、嚴謹,但大致思路是對的。


求知慾旺盛是好事,但以後不懂的東西更多,你根本不需要立馬知道答案,你只需要記下來以後自然就學到了。

cs知識是網狀的,你多學才能聯繫起來。

總結一下上面的回答,簡單說就是這個問題暫時不用深究,以後去看一下微機原理就明白了。

拿我個人來說,高一接觸的C++,大三才學微機原理,一點都不影響我中間5年寫程序。

人家問個問題,你們知道了就好好答,不知道的就閉嘴。


推薦閱讀:

調試程序有哪些技巧?
未來會不會出現這樣的編程語言?
是否數學不好就學不好編程?
程序員如何掌握編程思想?
像我這種情況,該如何繼續學習遊戲中實時渲染這方面知識?

TAG:編程語言 | 編程 | C編程語言 | 編譯原理 | CC |