C指針1:基礎

看了很多遍的指針,決定自己總結記錄一下。

先明確兩個概念:

1.指針:也就是內存的地址。

2.指針變量:也就是保存了內存地址的變量。

在計算機中所有的數據都必須放在內存中,然而不同類型的數據佔用不同的字節數。比如int佔用4個字節,char佔用1個字節,當這些數據載入內存之後爲了能夠正確的找到並訪問這些數據,我們就需要爲每個字節編上號碼,就像每個人都有一個身份證一樣,字節的編號也是唯一的,根據這些編號我們就可以準確的找到某個字節。

在32位的環境下,一個指針或地址佔用4個字節的內存,共有32位,理論上能夠訪問的虛擬內存空間大小爲2^32 = 0X100000000 Bytes(2表示2進制即0、1(每一位上有兩種可能0或者1)一種組合就代表一個地址),即4GB,有效虛擬地址範圍是 0 ~ 0XFFFFFFFF。

(2的32次方 等於4294967296)(2的32次方中0或者1的組合,每一種組合都代表一組地址)

(100000000(十六進制) = 4294967296(十進制))

(FFFFFFFF(十六進制) = 4294967295(十進制))

下面是4G內存中每個字節的編號(用16進制來表示)

上圖中我們將內存中字節的編號稱爲地址(Address)或者指針(Pointer),地址是從0開始依次增加的,對於32位環境程序能夠使用的內存爲4GB,最小的地址爲0,最大的地址爲0XFFFFFFFF。

#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
	int a = 100;
	char str[20] = "liminhao";
	int b[6] = {0,1,5,9,3,6};
	string c[5] = {"a","b","k","f","g"};//string是一個類
	printf("%#X, %#X\n", &a, str);
	cout << "a的地址:" << &a << endl;
	cout << "字符串名字str:" << str << endl;
	cout << "字符串str第一個元素str[0]:" << str[0] << endl;
	cout << "字符串str第一個元素地址:" << &str <<"  ,  "<<&str[0]<< endl;
	cout << "數組名b:" << b << endl;
	cout << "數組b第一個元素的地址:" << &b[0] << endl;
	cout<< "b[0]:"<<b[0] << endl;
	cout << "字符串名字c:" << c << endl;
	cout << "字符串c第一個元素地址:" << &c << "  ,  " << &c[0] << endl;
	return 0;
}

結果:

%#X表示以十六進制形式輸出,並附帶前綴0X。a 是一個變量,用來存放整數,需要在前面加&來獲得它的地址;str 本身就表示字符串的首地址,不需要加&。 但是在上述c++中我們可以看到,字符串名字並不表示字符串首地址,而是輸出的整個字符。

在C語言中用變量來存儲數據,用函數來定義一段可以重複使用的代碼,他們最終都要放到內存中才能共CPU使用(數據和代碼都以二進制的形式存儲到內存中,計算機無法從格式上區分某塊內存到底存儲的是數據還是代碼。當程序被加載到內存後,操作系統會給不同的內存塊指定不同的權限,擁有讀取和執行權限的內存塊就是代碼,而擁有讀取和寫入權限(也可能只有讀取權限)的內存塊就是數據。),正如之前在內存中所介紹的一樣,一段程序經過編譯之後變量名函數名都不存在,只剩下數據,地址和指令。

程序經過編譯後,CPU只能通過地址來獲取內存中的代碼和數據,程序在執行過程中會告知 CPU 要執行的代碼以及要讀寫的數據的地址。

CPU 訪問內存時需要的是地址,而不是變量名和函數名!變量名和函數名只是地址的一種助記符,當源文件被編譯和鏈接成可執行程序後,它們都會被替換成地址。編譯和鏈接過程的一項重要任務就是找到這些名稱所對應的地址。

需要注意的是,雖然變量名、函數名、字符串名和數組名在本質上是一樣的,它們都是地址的助記符,但在編寫代碼的過程中,我們認爲變量名錶示的是數據本身,而函數名、字符串名和數組名錶示的是代碼塊或數據塊的首地址。

參考:C語言中文網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章