和指標相關的問題
口訣1:
1.位址變數得位址,得誰位址指向誰
和指標相關的問題要畫圖: 內容變數畫房子,指標畫箭頭
---->口
一、"&" 取位址運算子,通過&運算子可以取出普通變數的位址;
二、"*" 有兩種意義:
1. 為指標標誌: 是否為指標標誌主要看前面是否有型別,此處有乙個int
2. 為指標運算子:
在等號右面為取值。*可以取出指標變數所指向的普通變數的值。
在等號左面為賦值。*可以將指標變數所指向的普通變數的值,修改為其他。
口訣2:有* 為內容值,不是讀就是寫。等號左面為賦值, 其餘都為取值。
3. 為乘法運算子。當且僅當左右的都為變數時。略。
如int a, b =20, c=30, d=40, *p; (正確,此處的*為指標標誌,只起到定義的左右,沒有取值和賦值的作用。是否為指標標誌主要看前面是否有型別,此處最前面有乙個int)
p=&d; (正確,p指向d的位址)
a=*p; (正確,此處的*為取值。最後結果a的值變為了d的值40)
*p =c; (正確,此處的*為賦值。最後結果d的值變為了c的值30)
*p =&b; (執行錯誤,左邊為內容值,右邊為位址,不等價)
和指標相關的等價表示式
若指標變數p指向變數a,即將變數a的位址賦給了指標變數p.
如:int a=20, int *p=&a;
則有如下結果:
a、*p <=> a
b、 p <=> &a
c、 &*p <=> &a <=> p
d、*&a <=> *p <=> a
e、 (*p)++ a++
(*p)-- a--
++(*p) ++a ++*p
--(*p) --a --*p
可以看出 * 和 & 是互逆的兩個運算子
所有的指標變數在記憶體中分配的位元組數相同 sizeof(指標) 永遠是 兩個位元組, 不管指標定義時是 int *, float * 還是 double * . 詳細如下
int *p1; 則 p1以後必須指向int 型別的變數。 但指標本身的長度,sizeof(p1) 為2個位元組(2*8bit -16bit)
float *p2; 則 p2以後必須指向float 型別的變數。 但指標本身的長度,sizeof(p2) 為2個位元組(2*8bit -16bit)
double *p3; 則 p3以後必須指向double 型別的變數。 但指標本身的長度,sizeof(p3) 為2個位元組(2*8bit -16bit)
四道例題:
例子1.
void fun (int *x , int *y)
main()
結果2, 1
4, 3
注意main在呼叫fun函式時, y 和x故意寫顛倒了。
例子2.
#include
void swap(int *p1, int *p2)
main()
如果在控制台輸入2 和 5
則輸出結果為
5, 2
原因: 在呼叫swap函式時使用了職稱,所以在swap函式內部對p1,p2 所引用的內容值的修改,會影響外面的a和b的值。
例子3:
#include
void swap(int *p1, int *p2)
main()
和2不同, swap函式中的temp為指標,temp=p1使得temp指向了2,p1=p2使得p1指向了5,p2=temp使得p2指向了5.
但最後的列印結果仍為
2,5原因是:雖然main中呼叫swap函式時使用了指標傳遞,但swap函式中的所有操作都是:將指標本身的修改,而沒有再次使用*操作符來修改「指標指向的內容值」
口訣3:沒有*的指標操作為位址,位址的賦值意味著改指向。
例子4:
#include
void swap(int *p1, int *p2)
main()
和2很像。但唯一不同是,temp定義為指標而不是普通變數。看上去似乎應該和2的輸出結果一樣,仍為
2,5 。
但實際執行時編譯器會報錯:非法的記憶體寫入。
原因是:temp為野指標,並沒有預訂指向**。如果指向系統區,則可能導致作業系統宕機或崩潰。
如果temp在定義後,馬上給乙個初始值,就不會有問題了。
指標、陣列的等價符號
若將陣列作為形參,則將陣列名作為指標變數來處理。
int fun(int a[10]) <=> int fun(int *a) <=> int fun(int a)
可以看出,口訣4: &與*互逆。 *與等價, &與互逆
例子5:
int s[10], a, b;
in d[3][6];
int *p;
p=&a; //p 指向了整數a
p = &s[2]; //p指向了s陣列的第二個元素
p= &d[2][4];////p指向了d陣列的第二行、第四列的元素。
所以,以上的語句都是對的。
上面的例子:
1. 定義了乙個int s[10]; 則 s等同於 &s[0]. 即,看到乙個陣列,就馬上聯想到他代表的是陣列第乙個元素的位址。
在c語言中規定,資料名代表陣列的首位址,並且是乙個位址常量
2. 另外,如果定義了乙個指標 int *ppp = s; 則 ppp 定價於s, 同時等價於 &s[0]。
指標的加減:
例子6:
float a[10]; float *p;
p=&a[4]; 則p-3指向?
先畫圖:
a[0] | a[1] | a[2] | a[3] | a[4] | ...
p的初始位置指向了 a[4], 則 p-3 為向前3個,指向了 a[1]
口訣5: 指標的加減是向前或向後移動了n個元素
若
int a[n], *p=a;
則有:存在等價表示式:
p+i <=> a+i <=> &a[i] 代表的是第i個元素的位址
元素四等價:
存在等價表示式:
1. *(p+i) <=> *(a+i) <=> a[i] 代表的是第i個元素的值
2. 另外,還有 p[i] <=> a[i] 。 p[i] 的用法不多見,但無任何錯誤,代表的也是第i個元素的值。原因是p和a完全等價。
a) *(p+i) <=> *(a+i) <=> a[i] <=> p[i]
b) p++ <=> ++p <=> p+=1 <=> p=p+1
c) p-- <=> --p <=> p-=1 <=> p=p-1
d) *p++ <=> *(p++)
說明:* 與 ++ 的運算優先順序一樣,所以按照從右到左的結合原則,先執行++,後執行*
++在p的後面,為執行後再加。即先把p的值取出,指標再加1.
e) *++p <=> *(++p)
++在p的前面,為先加再執行。即先把指標加1, 再把移動後的p所指向的值取出,
f) (*p)++ <=> ++(*p) <=> ++*p
將p的內容自增
g) (*p)-- <=> --(*p) <=> --*p
將p的內容自減
c語言之指標與陣列
考慮該例子 int calendar 12 31 該語句宣告了calendar是乙個陣列,該陣列擁有12個陣列元素,其中每個元素都是乙個擁有31個整型元素的陣列 而不是反過來理解 因此,sizeof calendar 的值是12 31 372與sizeof int 的乘積。如果calendar不是用...
C語言之指標與陣列
前言 訪問陣列元素既可以使用陣列名加下標的方法,也可以使用指標的方法。但使用指標的方法可以使 更緊湊 更靈活 更高效。一 幾個概念而陣列名代表陣列的起始位址,即陣列的指標。說明 二 指標訪問一維陣列 1 利用指標名構造指標表示式 例如 定義整型陣列a,int a 6 2 利用指標變數訪問陣列 三 指...
C語言之辨別指標陣列與陣列指標
我們先來說一下指標陣列,顧名思義,這是乙個存放指標型別的陣列 從定義上來看 int p 3 沒有括號括起來它還是陣列這裡我還是寫乙個程式來理解一下 include intmain for int i 0 i 3 i return0 程式執行的結果 1 23指向指標的陣列 又稱行指標 如何定義 int...