看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《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 也可以填入 ┌────┬────┬────┬────┬──┬───┬───┐ Addr152 │ 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