C C 有意思的指標(1)

2021-10-24 17:36:24 字數 2833 閱讀 4745

在c/c++中指標是乙個常用的型別,但同時指標也是乙個重要且有意思的概念。這個概念說大了與量子糾纏什麼還能聯絡在一起,也可以與宇宙空間聯絡起來。而我更喜歡它另外乙個角度的理解:玄幻**裡男主角的空間戒指。

記得以前看玄幻類**時常羨慕男主角的空間儲物戒指,想放什麼就放什麼,還可以在信物戒指裡面住,甚至生活都可以。裡面放的都是奇珍異寶,鳥語花香等等,總之它是乙個與世無爭的空間。只要你有乙個這樣的戒指你就能獲得具大的空間,這裡的空間是指宇宙空間。而計算機相當於現實世界的虛擬,它也有自己的空間,這個空間稱為記憶體空間。而要獲得記憶體空間就需要通過記憶體位址訪問,指標就充當了這樣乙個角色,作為記憶體空間的鑰匙,開啟記憶體空間的大門。只是這個記憶體空間只能儲存資料(或說暫存器狀態)。

普通人理解的計算機儲存我們資料及影象資料,但其它是儲存了0或1的狀態。記憶體中的資料也是,記憶體中的2g記憶體空間大小是如何來的。

記憶體空間最小計算單元為位元組即8bit位,為了便於理解只表示正數,表示的範圍是(00000000 - 11111111)0~255,也可以說一位元組記憶體能記錄256種狀態。程式中使用的char資料型別即占用乙個位元組。

現在嵌入普通使用的都是32位的記憶體位址線,那麼代表它能訪問的記憶體空間大小為2的32次方位元組。

2的32次方 = 4294967295/1024 = 4193280kb = 4095mb = 4gb 就是說4g記憶體可以儲存4294967295種狀態。

我們可以通過程式中使用指標位址來訪問到記憶體的每一位元組記憶體空間。當然有些記憶體空間特殊用處不能讓使用者隨意訪問到這個另外的話題。

雖說乙個位元組能表示256種狀態,但在同一時刻它只能處在256種狀態中的一種。所以記憶體空間乙個位元組在某時刻只能表示0~256之間的乙個數值。比如我們一張假定解析度為1024x600,16位深度,那麼顯示器要顯示一張這個需要到記憶體讀取多少記憶體空間呢。需要102460016狀態來表示一張即1200kb資料量。

說到記憶體空間就必須要提到資料型別,在高階語言很都沒有資料型別一說,但c/c++是面向記憶體操作的程式語言,需要按照一定的方式來訪問記憶體空間,這個約定的方式即是資料型別。

可以這樣,資料型別是程式設計師與cpu約定的一種讀取記憶體的方式,指定資料型別後cpu按照指定型別去訪問記憶體空間。避免隨意訪問記憶體空間導致的錯誤。

如定義char型別資料那麼cpu就讀取記憶體1個位元組記憶體空間,int讀取4位元組記憶體空間。那麼定義的變數即是資料型別能訪問到的記憶體空間大小。即 char a; 定義變數a為char型別資料,cpu通過a變數名的首位址訪問記憶體空間1個位元組。 int b = 4;那b變數名能訪問到記憶體空間4個位元組,即a變數占用4位元組記憶體空間。

指標變數說白了就是儲存記憶體位址的變數。所以指標變數必須也是給定資料型別,這個cpu才知道到位址記憶體空間讀取多少位元組空間。char* a;定義a為指標變數,a變數中儲存了一片記憶體空間的位址,至於這個指向的記憶體空間是多大或說通過這個指標變數能訪問到多少的記憶體空間則於資料型別決定。這裡指標能訪問到1個位元組記憶體空間。

int* b; 定義乙個整型型別指標,或說定義變數b儲存的位址能訪問到4位元組的記憶體空間。因整型型別占用4位元組記憶體。

即然資料型別是程式設計師與cpu之間約定的讀取記憶體的方式,所以當定義了乙個指標變數時,那麼在指標變數的賦值或指向其它空間時,這個讀取的約定必須是相同的。即指標賦值時指標指向的內容資料型別必須相同,或說指標型別相同。

示例:

int age =10;

int* a =

&age;

//&取age的位址運算,約定cpu讀取記憶體方式為int型別即4位元組讀取

指標也是一種資料型別,它通常佔4位元組記憶體空間(依不同平台佔位元組數不同)。

char* a; //變數a存放char指標型別

int b; // 變數b存放int* 指標型別

指標型別代表了2種含義

從上面內容可以看到,指標變數可以儲存記憶體空間首位址,相當是拿到記憶體中某塊儲存空間的入口號碼。有了這個位址,便可以訪問這片記憶體區域,但具體怎麼訪問或說能訪問到這片記憶體區域的大小則由資料型別指定。

想象下記憶體空間就是宇宙空間,我們申請記憶體空間,分為受型別限制大小的方式,即使用了資料型別(這個資料型別可以自定義)。或不使用資料型別,申請一片記憶體空間。

int* a = (int*)malloc(sizeof(int)); //也可以使用int* a = (int*)malloc(sizeof);

void* b = (void*)malloc(size);

第乙個int* a由於這指標型別為int型別,所以申請空間後需要強制型別轉換成(int)型別,至於申請的記憶體空間大小則不是必須為sizeof(int)的,你可以指定任意大小記憶體空間。只是指標型別為int*型別,就是cpuf讀取記憶體只能是首位址偏移4位元組,如果申請記憶體更大,也訪問不到浪費記憶體而已。

但是變數b就不同,它沒有跟cpu約定怎麼讀取記憶體空間,所以它申請任意大小的空間都可以通過指標訪問到。

至於指標變數的增減操作,則依語言預設是增加乙個資料型別的大小。這裡也就很好理解,因為指定了資料型別那麼變數的偏移操作肯定要以資料型別為最小單元來偏移,否則訪問到其它地方資料就亂了(其它也可以強制型別轉換那樣想怎麼訪問就怎麼訪問,有時我們把int型別轉換成char就是這個原理)。

說白了就是程式設計師與cpu約定讀取記憶體的方式變了,這個如果想正常使用只能是從大轉成小,如果小轉成大則會訪問到超出資料型別的記憶體空間,導致資料錯誤(錯誤是未知的)。

這樣就理解了什麼是強制型別轉換了。強制型別轉換從大資料型別轉到小資料型別是可以正常讀取的,如int轉換成char型別可以訪問記憶體前1個位元組內容,後面3位元組內容就丟失了。如果char轉int則不行,會訪問到指標記憶體空間外的記憶體。這樣可能會損壞其它記憶體空間資料。

指標其它用處,只是指標原理的延伸處理方。如函式指標就是函式名即是乙個指標變數,陣列名也類似。

更詳細的指標使用,待續。。。。

用於個人理解,僅供參考。

C C 有意思的指標(2)

普通變數的定義與使用不存在很大的區別,定義了直接使用即可。但指標的定義與使用是需要作區分的。int p nullptr 定義時 指記憶體位址,或說指向的記憶體區域首位址 cout p endl 指標使用時 是指對p存放的位址解引用,按p的資料型別讀取記憶體資料。這對指標型別作解析 int 型別中的 ...

C C 有意思的指標(4)

指標可以讓我們申請記憶體空間,並使用指標讀寫指定的記憶體區域。但還有另外一種情況,我們想把資料放到指定的記憶體區域,或說在某些暫存器與記憶體統一編址的平台,想要訪問某段暫存器,並更改暫存器的值。通過檢視晶元手冊,知道裝置暫存器位址,然後通過把位址值轉換成指針對這段暫存器記憶體進行讀寫。我們通過取位址...

有意思的話

1 要麼忍,要麼殘忍 2 下輩子我要做你的一顆牙,至少,我難受,你也會疼 3 心不動,則不痛 4 我們唯一的關係是沒有關係。5 你會流淚,並不代表真的慈悲 我會微笑,並不代表一切都好。6 孤單 是 你心裡面沒有人 寂寞 是 你心裡有的人卻不在身邊 7 冬天裡你給了我乙個夏天的夢 卻把我在春天叫醒了 ...