1. 程式人生 > >C語言指針是什麽?C語言指針的概念。

C語言指針是什麽?C語言指針的概念。

格式 獲取 權限 ret 需要 場景 不同的 一段 存儲空間

計算機中所有的數據必須存放在內存中,不同的類型的數據占用的內存字節也不同,int型占4字節,char型占一字節,為了正確訪問這些數據,必須為每個一個自己都編上號碼,就像倉庫一樣,每個倉庫都會有自己的編號,來定位到具體的倉庫。沒有字節的編號都是唯一的,根據編號就可以準確的找到某一個字節。
如: char a =‘a’;
這一句話中a就是一個指針地址他指向了內存中一個char型1字節的內存空間 ,而這個字節內存儲的數據是‘a’,所以char a中a存儲的數據並不是‘a’而是內存中1個字節空間的內存地址。是用十六進制表示的一個內存地址編號,如:0x1000;
如圖是4G內存中每個字節的編號(以十六進制表示):
int i ;
0x0000 0x0001 0x0002 0x0003
0xFFFFFFFD 0xFFFFFFFE 0xFFFFFFFF 0xFFFFFFFC

我們將內存中字節的編號稱為地址(Address)或指針(Pointer)。地址從0開始依次增加,對於32位環境中,程序能夠使用的內存為4GB,最小的地址為0,最大的地址是0XFFFFFFFF.因為十六進制0XFFFFFFFF對應的二進制就是11111111111111111111111111111111 。
下面的代碼演示了如何輸出一個地址:
#include<stdio.h>

int main(){

int a=100;
char str[20]=”zheshiyizifuchuan”;

printf(“%#X,%#X\n”,&a,str);
return 0;
}

運行結果:
0XBF80E1E4,0XBF80E1F8.
這裏解釋一下為什麽他們的間隔是4,因為int型a在內存中占四字節,每個字節都會有自己獨特編號指針,a在內存中的分布是
0XBF80E1E4 0XBF80E1E5 0XBF80E1E6 0XBF80E1E7

而char str[20]數組中的內存分布是
0XBF80E1F8 0XBF80E1F9 0XBF80E1E2 ……此處省略中間的地址… 0XBF80E1V8
而取str的內存地址是,取的是char str[20]數組中的首元素的地址,所以str的內存地址是0XBF80E1F8。

%#X表示以十六進制形式輸出,並附帶前綴0X。a是一個變量,用來存放整數需要在前面加&來獲取它的地址;str本身就表示字符串的首地址,不需要加&。

C語言中有一個控制符 %p,專門用來打印出以十六進制形式表示的變量內存地址,不過,%p的輸出格式並不統一,有的編譯器帶0X前綴,有的不帶,所以此處我們並沒有采用

一切都是地址(指針)
C語言用變量來存儲數據,用函數來定義一段可以重復使用的代碼,他們最終都要放到內存中才能供CPU使用。
註釋:C語言中數據的存儲都是在聲明的變量中,換句話說就是聲明的變量,變量的指針指向的是內存的數據存儲層,如果想要存儲一條數據就需要聲明一個變量而變量不存儲數據,變量只存儲聲明的這個變量的類型字節空間在內存中的編號,而數據存儲在聲明的類型的字節空間中,變量只是一個指向這塊空間的指針。變量的指針是指針內存數據層,而函數其實本質上也是一個指針,函數名也是一個指針。而函數名指向的 內存空間是代碼層。其實聲明一個函數就是在內存的代碼層中聲明了一塊空間在存儲編寫的代碼,而函數名其實內存儲的其實就是指向這一塊內存空間的地址指針。所以從這一層面上來看的話,程序中不管是變量還是函數都是存儲在內存中的,而我們編寫的變量名,函數名,數組名,字符串名,其實都是指向內存空間的字節編號,而他們的存儲空間在內存中也會在不同的層中,這也是方便cup的讀取。而cup讀取執行程序時,會根據變量名和函數名提供的內存字節地址準備的去不同的內存層空間中讀取不同的數據。
數據和代碼都是以二進制的形式存儲在內存中,計算機無法從格式上區分某塊內存到底存儲的是數據還是代碼,當程序被加載到內存後,程序系統會給不同的內存指定不同的權限,擁有讀取和執行權限的內存塊就是代碼,而擁有讀取和寫入權限(也可能只有讀取權限)的內存塊就是數據。
註釋:程序中聲明的變量和代碼最終都會轉為二進制代碼存儲在計算機的內存中,但是計算機無法區分出哪裏的內存存儲的數據是數據,哪裏的是代碼,所以需要程序系統給不同的內存空間設定不同的權限,來區分內存空間中存儲的數據還是代碼,這也是內存出現不同層的原因。
CPU只能通過地址來取得內存中的代碼和數據,程序在執行過程中會告知CPU要執行的代碼以及要讀寫的數據的地址。如果程序不小心出錯,或者開發者有意為之,在CUP要寫入數據時,給它的一個代碼區域的地址,就會出現內存訪問錯誤,這種內存訪問錯誤會被硬件和操作系統攔截,強制程序崩潰,程序員沒有挽救的機會。
註釋:程序在執行時CPU只能通過地址去內存中讀取數據,而代碼和數據是存放在不同的內存層中如果程序在編寫中設置的變量地址或者函數地址的數據層不對時,那麽CPU在讀取數據或代碼時會因為權限的問題而被硬件和操作系統攔截,從而內存數據讀取失敗導致程序崩潰,因為這個過程是編寫好的而且程序執行非常快的,所以程序員沒有計劃挽救。
CPU訪問內存時需要的是地址,而不是變量名和函數名!變量名和函數名只是地址的一種助記符,當源文件被編譯和連接成可執行程序之後,他們都會被替換成地址。編譯和連接過程的一項重要任務就是找到這些名稱所對應的地址。
註釋:這句話很重要,這句話也是地址的核心,變量名在聲明時會有一個自己獨特的地址,而程序在編譯時也會把聲明的變量名轉換為指針,在CPU訪問內存是就是需要的我們之前聲明的變量轉換之後的地址指針。而編譯就是負責這個轉換的過程。

假設變量 a b c 在內存中的地址分別是0X1000 0X20000 0X30000,那麽加法運算c=a+b;
將會被轉成類似下面的形式:
0X3000=(0X10000)+(0X20000);
()表示取值操作,整個表達式的意思是,取出地址0X10000和0X20000上的值,將他們相加,把相加的結果賦值給地址為0X30000的內存。

變量名和函數名為我們提供了方便,讓我們在編寫代碼的過程中,可以使用易於閱讀和理解的英文字符串,不用直接面對二進制地址,那場景簡直讓人崩潰。

需要註意的是,雖然變量名,函數名,字符串名,和數組名,在本質上是一樣的,他們都是地址的助記符,但在編寫代碼的過程中,我們認為變量名是表示的是數據本身,而函數名和數組名表示的是代碼塊或數據塊的首地址。
註釋:這裏的原因是因為變量名指向的是一個一種數據類型的內存空間地址,而函數名,字符串名,數組名,指向的是一塊內存中連續的數據類型空間的第一個字節的地址。

本文章參考c.biancheng.net.中c語言指針是什麽的博文和添加自己的主觀想法完成的編寫。
原文:http://c.biancheng.net/view/1990.html

C語言指針是什麽?C語言指針的概念。