作者closer76 (克樓瑟)
看板C_and_CPP
標題Re: [問題] 請教指標操作方式
時間Fri Jun 17 18:30:46 2022
我們先來看一下你定義出來的 struct,在記憶體中長什麼樣。
(假設你的 int 長度也是 16-bit,系統為 little-endian)
: typdef struct{ typedef struct{
: int A; int B;
: char *data; char userData[8];
: } MSG_OBJ } MSG_OBJ_USE
MSG_OBJ MSG_OBJ_USE
Address +------------+ +-------------+
x | | | |
x+1 | A | | B |
+------------+ +-------------+
x+2 | | | userData[0] |
x+3 | data | | userData[1] |
+------------+
x+4 | userData[2] |
x+5 | userData[3] |
x+6 | userData[4] |
x+7 | userData[5] |
x+8 | userData[6] |
x+9 | userData[7] |
+-------------+
宣告指標、和宣告陣列,記憶體長得就會不一樣。
然後,我們假設 compiler(實際上是 linker)把你的 globalData[8] 放在 0x9518
這個位置:
: char globalData[8] = {0};
Address +---------------+
0x9518 | globalData[0] |
0x9519 | globalData[1] |
:
0x951F | globalData[7] |
+---------------+
然後你的 obj 放在 0x9520:
: MSG_OBJ_USE obj;
由於你宣告在 global scope,我們假設整段空間的內容預設都是 0。
: void getDataFun(MSG_OBJ* b)
: {
: b->data = globalData;
: }
接下來這行有些 tricky....
getDataFun() 要接收的是 MSG_OBJ*
但你傳進的去的是 MSG_OBJ_USE*
: getDataFun(&obj);
現在大部份的 compiler 會因為 type 不合而發生 error(最少也是 warning),
但如果 compiler 讓你過的話,等於是
「把 0x9520 開始的記憶體空間,當成是 MSG_OBJ 來處理」。
因此,這行執行完後,你的 obj 的內容會變成:
MSG_OBJ_USE
Address +-------------+
0x9520 | 0x00 |
0x9521 | 0x00 |
+-------------+
0x9522 | 0x18 |
0x9523 | 0x95 |
0x9524 | 0x00 |
0x9525 | 0x00 |
0x9526 | 0x00 |
0x9527 | 0x00 |
0x9528 | 0x00 |
0x9529 | 0x00 |
+-------------+
Why?
因為 getDataFun() 把 0x9520 當成 MSG_OBJ 來處理,
所以就把 globalData 的位址(也就是 0x9518)
填到原本 MSG_OBJ::data 該在的位置(也就是 0x9520+2 & 0x9520+3)。
: char* ptr = (char*)(*(uint16_t*)obj.useData); //平台指標為16 bits
一步一步看:
Type Value
obj.useData ==> char* 0x9522
(uint16_t*)obj.useData ==> uint16_t* 0x9522
*(uint16_t*)obj.useData ==> uint16_t 0x9518(obj.useData的內容)
(char*)*(uint16_t*)obj.useData ==> char* 0x9518
因此 ptr 的內容就是 0x9518,也就是 globalData 的位址。
: //Step.2
: for(int i=0;i<8;i++);
: {
: obj.useData[i] = ptr[i];
: }
從前面的分析來看,這個 loop 就是把 globalData 的值複製到 obj.userData...
如此而已。
: //問題:
: Step1.的動作意思是useData array上面放的值是指標, 所以才可以取值(*)給ptr
: 然後用step2把copy資料.
: 我的疑問是b->data = globalData應該是把&globalData[0] 指定給b->data而已.
其實我看不懂你的問題。 XD
不過希望前面的分析能幫到你的忙。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.137.47.224 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1655461848.A.2E7.html
※ 編輯: closer76 (223.137.47.224 臺灣), 06/17/2022 18:38:20
推 OnlyRD: 通常這種太特殊的寫法,如果沒有特殊目的,基本上 06/17 21:32
→ OnlyRD: 都屬於設計有問 06/17 21:32
→ OnlyRD: 題的程式,不僅維護困難,容易造成問題,語意也不 06/17 21:32
→ OnlyRD: 清楚。有些程式 06/17 21:32
→ OnlyRD: 為了效能問題,會採用特殊的手法,但是這段程式看 06/17 21:32
→ OnlyRD: 起來效能更差, 06/17 21:32
→ OnlyRD: 記憶體也沒省。 06/17 21:32
推 CoNsTaR: 樓上,說實話這真的還好,它當然不是什麼設計多好的程式 06/17 22:32
→ CoNsTaR: ,但真的還算是清楚易懂,很多比這慘十倍以上的程式你還 06/17 22:32
→ CoNsTaR: 不是要捏著小鳥去處理 orz 06/17 22:32
推 OnlyRD: 也是,但我現在做的事情幾乎都是from scratch,架 06/19 03:20
→ OnlyRD: 構跟基底我打的 06/19 03:20
→ OnlyRD: ,當然不想折磨別人。 06/19 03:20
推 wulouise: 猜先有MSG_OBJ後有*_USE 然後有地方沒改*_USE洞被亂補 06/19 08:27