三. 指標使用
四. 函式和指標
五. const 和指標
指標是另外一種型別的復合型別,復合型別是指基於其它型別定義的型別
(意思是說指標是指向什麼型別,那麼指標本身就是什麼型別)
指標其實就是程式資料在記憶體中的位址,而指標變數是用來儲存這些位址的變數
記憶體是乙個很大的,線性的位元組陣列。每乙個位元組都是固定的大小,由8個二進位制位組成。最關鍵的是,每乙個位元組都有乙個唯一的編號,編號從0開始,一直到最後乙個位元組,這個編號就是所謂的位址。
指標的值(虛擬位址值)使用乙個機器字長
來儲存,也就是說,對於乙個機器字長為w位的電腦而言,它的虛擬位址空間是0~[2的w次冪] - 1,程式最多能訪問2的w次冪個位元組。這就是為什麼xp這種32位系統最大支援4gb記憶體的原因了。
機器字長 是指計算機進行一次整數運算所能處理的二進位制資料的位數(整數運算即定點整數運算,常見的有8位、16位、32位、64位等)
1. 變數在記憶體中的儲存
舉個例子: int a = 1;
因為 int 型別在 32 位作業系統中佔 4 個位元組,那麼 記憶體中 位址 0028ff40到0028ff43之間4個位元組 就儲存了變數a ,但是 指標只儲存了首位址值 0028ff40 作為 變數 a 的指標位址,所以佔據記憶體的位址就是位址值最小的那個位元組的位址
2. 指標在記憶體中的儲存
再舉個例子:
int a =1;
// 宣告乙個指標 格式 : 變數型別 * 指標變數名 = &變數名
// &變數名 表示獲取變數在記憶體中的首位址值
// * 表示是乙個指標
int* p =
&a;
p++;
指標也是一種資料型別,在32位程式裡,所有型別的指標的值都是乙個32位整數,因為32位程式裡記憶體位址全都是32位長,所以無論是什麼型別的指標,在32為系統中 指標都是占用4個位元組。在上例中,指標p 的型別是int *,它指向的型別是int,它被初始化為指向整形變數a,接下來的第3句中,指標p 被加了1,編譯器是這樣處理的:它把指標p的值加上了sizeof(int)大小的位元組,在32位程式中,是被加上了4。由於位址是用位元組做單位的,故p所指向的位址由原來的變數a的位址向高位址方向增加了4個位元組。
這個時候可以列印一下 p 指向的的記憶體位址資料
int
main()
第一次列印正確值,因為第一次列印的時候,指標p指向的是變數a的位址值
第二次列印了乙個負數,因為 p++ 操作是改變指向的記憶體位址,而不是把原來的4位元組擴張為8位元組
1. 定義指標物件
定義指標變數時,在變數名前寫乙個 * 星號,這個變數就變成了對應變數型別的指標變數。必要時要加( ) 來避免優先順序的問題:
int
* p_int;
//指向int型別變數的指標
double
* p_double;
//指向double型別變數的指標
person * p_struct;
//類或結構體型別的指標
int*
* p_pointer;
//指向 乙個整形變數指標的指標
int(
*p_arr)[3
];//指向含有3個int元素的陣列的指標
int(
*p_func)
(int
,int);
//指向返回型別為int,有2個int形參的函式的指標
2. 獲取指標指向的資料int a =1;
int* p =
&a;printf
("%p\n"
,&a)
;// 變數a的所在的記憶體位址
printf
("%p\n"
, p)
;// 指標p的值 就是a的位址
printf
("%d\n"
,*p)
;printf
("%p\n"
,&p)
;//指標p的所在的記憶體位址
3. 指標值的狀態
空指標,意味著指標沒有指向任何物件 例:int * p;
無效指標(野指標) 例:int * p = 0x00001;
4. 指標的算數運算
指標可以加上或減去乙個整數。指標的這種運算的意義和通常的數值的加減運算的意義是不一樣的,指標的運算是有單位的
如上面 2.2 介紹 p++ 的例子:
指標p的型別是int *,它指向的型別是 int,p加1,編譯器在1的後面乘上了單位sizeof(int)
若p+3,則編譯之後的位址應該是 p的位址加 3 * sizeof(int)
指標運算最終會變為記憶體位址的元素,記憶體又是乙個連續空間,所以按理只要沒有超出記憶體限制就可以一直增加。這樣前面所說的指標值的狀態第二條就很好解釋了。
4.1 函式的引數和指標
實參傳遞給形參,是按值傳遞
的,也就是說,函式中的形參是實參的拷貝份
,形參和實參只是在值上面一樣,而不是同乙個記憶體資料物件。這就意味著:這種資料傳遞是單向的,即從呼叫者傳遞給被調函式,而被調函式無法修改傳遞的引數達到回傳的效果
void
change
(int a)
intmain
(void
)
有時候我們可以使用函式的返回值來回傳資料,在簡單的情況下是可以的,但是如果返回值有其它用途(例如返回函式的執行狀態量),或者要回傳的資料不止乙個,返回值就解決不了了。
傳遞變數的指標可以輕鬆解決上述問題:
void
change
(int
* a)
intmain
(void
)
有時我們會傳遞類或者結構體物件,而類或者結構體占用的記憶體有時會比較大,通過值傳遞的方式會拷貝完整的資料,降低程式的效率。而指標只是固定大小的空間,效率比較高
5.1 指向常量的指標
int a =1;
int b =2;
// 指向常量的指標,它指向的值不能修改,但是執行可以變
const
int* p =
&a;//將const放在型別前面或者後面,二者的意義完全相同
//int const * p;
// *p = b; // 編譯報錯
p =&b;// 通過
b =3;
// 通過
cout <<
*p << endl;
// 輸出:3
5.2 常量指標int a =1;
int b =2;
int*
const p =
&a;// p = &b; // 編譯報錯
*p =3;
cout <<
*p << endl;
C 面試 (1) 指標
指標是c 中一類頗具特色的資料型別,允許直接操作記憶體位址,實現記憶體的動態分配。指標問題通常包括指標常量,常量指標,陣列指標,指標陣列,函式指標,指標傳值等。指標和引用的區別 非空區別。在任何情況下都不能使用指向空值的引用。因此如果你使用乙個變數並讓它指向乙個物件,但是該變數在某些時候也可能不指向...
C 基礎總結 4 指標
指標是乙個變數,其儲存的值是位址,而不是值本身。有點類似於組成原理裡面的變址定址 在討論指標之前,我們先來看看如何尋找常規變數的位址。只需對變數引用取位址符 就行了。如下面一段 duck變數為int型變數,其分配的位址是1000,裡面儲存的值是12,而birding是乙個int型指標變數它本身的位址...
C語言基礎四 指標
指標表示乙個位址,什麼型別的指標就應該指向什麼型別的記憶體空間,例如int 型別的指標就應該指向乙個int型別的空間。int a 7 int p null 指標的定義 p a 指標的繫結 p 5 指標的解引用對於同型別指標p1,p2,一般有這幾種運算 p1 3,p1 3,p2 p1 int a 5 ...