※ 引述《leo19866 (ice)》之銘言:
: 小弟最近在看C語言的書
: 看到一題關於指標的問題
: 希望有人能為小弟解惑
先假定 sizeof(double) == 8 成立,且 CHAR_BIT == 8 也成立
(看不懂這兩句的話,就記,假設 double 吃了 8 bytes 記憶體大小 )
然後假設 sizeof(double*) == sizeof(double**) == 4 bytes 也成立 [Lemma]
: double a[4]={10.0,20.0,30.0,40.0};
┌────┬────┬────┬────┬──┬───┬───┐
Addr│ ???? │ ???? │ ???? │ ???? │... │ │ │
├────┼────┼────┼────┼──┼───┼───┤
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ │ │
├────┼────┼────┼────┼──┼───┼───┤
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ │ │
└────┴────┴────┴────┴──┴───┴───┘
: double *pa=&a[1], **ppa=&pa;
┌────┬────┬────┬────┬──┬───┬───┐
Addr│ ???? │ ???? │ ???? │ ???? │... │ ???? │ ???? │
├────┼────┼────┼────┼──┼───┼───┤
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ pa │ ppa │
├────┼────┼────┼────┼──┼───┼───┤
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ ???? │ ???? │
└────┴────┴────┴────┴──┴───┴───┘
pa 存的內容,剛好就是 a[1] 的 Addr (紅色對紅色),
而 ppa 的內容,剛好就是 pa 的 Addr (綠色對綠色) ,
pa 和 ppa 在記憶體位置裡不一定是連續的,但我不好畫,只好畫在旁邊。
: int i = 4 ;
: 已知pa=160,ppa=280
i = 4 我畫不下了,就先跳過 Orz,
先看 pa = 160 --> 紅色問號填上 160,
再看 ppa = 280 --> 綠色問號填上 280
┌────┬────┬────┬────┬──┬───┬───┐
Addr│ ???? │ 160 │ ???? │ ???? │... │ 280 │ ???? │
├────┼────┼────┼────┼──┼───┼───┤
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ pa │ ppa │
├────┼────┼────┼────┼──┼───┼───┤
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ 160 │ 280 │
└────┴────┴────┴────┴──┴───┴───┘
再來是,因為已知一個 double 是佔 8 bytes,所以 a[0]~a[3] 的 Addr 也可以填入
┌────┬────┬────┬────┬──┬───┬───┐
Addr│ 152 │ 160 │ 168 │ 176 │... │ 280 │ ???? │
├────┼────┼────┼────┼──┼───┼───┤
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ pa │ ppa │
├────┼────┼────┼────┼──┼───┼───┤
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ 160 │ 280 │
└────┴────┴────┴────┴──┴───┴───┘
: 回答下列各式的值
: 1.pa[3]
pa[3] 實際上就等於是 *(pa+3), 分解動作,
(1) *(pa+3) : 去找 pa 指向的 Addr ,取得 Addr 160
pa
┌──────────────────────────┐
↓ │
┌────┬────┬────┬────┬──┬───┬───┐ │
Addr│ 152 │ 160 │ 168 │ 176 │... │ 280 │ ???? │ │
├────┼────┼────┼────┼──┼───┼───┤ │
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ pa │ ppa │ │
├────┼────┼────┼────┼──┼───┼───┤ │
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ 160 │ 280 │ │
└────┴────┴────┴────┴──┴───┴───┘ │
└─────────┘
(2) *(pa+3) : 因 pa 指向 double ,+3 就是以剛剛找到的 Addr 160,往右移動 3
個 double 大小之位置,所以定位到了 160 + sizeof(double) * 3
= 160 + 8*3 = 160 + 24 = 184
pa+3 (指向 184)
┌────────────┐
↓ │
┌────┬────┬────┬────┬──┬───┬───┐ │
Addr│ 152 │ 160 │ 168 │ 176 │... │ 280 │ ???? │ │
├────┼────┼────┼────┼──┼───┼───┤ │
Var │ a[0] │ a[1] │ a[2] │ a[3] │... │ pa │ ppa │ │
├────┼────┼────┼────┼──┼───┼───┤ │
內容│ 10.0 │ 20.0 │ 30.0 │ 40.0 │... │ 160 │ 280 │ │
└────┴────┴────┴────┴──┴───┴───┘ │
└─────────┘
(3) *(pa+3) : 剛定位到的 Address 是 184,去看裡面的內容,
疑!發現這塊記憶體程式沒用到吶!於是程式就丟出 bug...
: 2.pa+2
(1) 先去看 pa 的內容,是 160
(2) 以 160 為基礎 ,移了 2 個 double 大小,得到 160 + 2*8 = 176,是一個 Addr
: 3.pa+i
(1) 先去看 pa 的內容,是 160
(2) i 的內容是 4,160 移 4 個 double 大小,得 160 + 4*8 = 192,是一個 Addr
: 4.ppa+i
(1) ppa 內容是 280,先定位到 280
(2) ppa+i ,由於 ppa 是 double ** ppa ; 是指向 double * 指標,所以移動
i 個 double * 大小,然後上面假設有說了,假設 double * 大小是 4 ,所以
變成 280 移動 4 個指標大小 = 280 + 4*4 = 280+16=296
: 5.*pa+i
(1) pa 內容是 160,先定位到 160
(2) *pa ,去 160 的地方看內容(也就是 a[1]),得到 20.0
(3) 再將 20.0 + i , 得到 20.0 + 4 = 24.0
---
上面看懂後,下面的還蠻無聊的,剩下的就不講了。
: 6.*(pa+2)
: 7.*ppa
: 8.**ppa+1
: 9.*ppa+1
: 10.*(*ppa+1)
: 如果能解釋一下更好
: 在此先謝過了
------------
Lemma
早期的書可能都是假設指標大小是 4 bytes,然後一般的面試、考試也都這個假設,
但對現今 x64 充斥的情況下,指標大小多為 8 bytes 居多,
故其實有必要強調指標大小到底是多大比較適合。
--
If there is no tomorrow,
I want to see u last time.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.177.74.188