作者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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1655461848.A.2E7.html
※ 编辑: closer76 (223.137.47.224 台湾), 06/17/2022 18:38:20
1F:推 OnlyRD: 通常这种太特殊的写法,如果没有特殊目的,基本上 06/17 21:32
2F:→ OnlyRD: 都属於设计有问 06/17 21:32
3F:→ OnlyRD: 题的程式,不仅维护困难,容易造成问题,语意也不 06/17 21:32
4F:→ OnlyRD: 清楚。有些程式 06/17 21:32
5F:→ OnlyRD: 为了效能问题,会采用特殊的手法,但是这段程式看 06/17 21:32
6F:→ OnlyRD: 起来效能更差, 06/17 21:32
7F:→ OnlyRD: 记忆体也没省。 06/17 21:32
8F:推 CoNsTaR: 楼上,说实话这真的还好,它当然不是什麽设计多好的程式 06/17 22:32
9F:→ CoNsTaR: ,但真的还算是清楚易懂,很多比这惨十倍以上的程式你还 06/17 22:32
10F:→ CoNsTaR: 不是要捏着小鸟去处理 orz 06/17 22:32
11F:推 OnlyRD: 也是,但我现在做的事情几乎都是from scratch,架 06/19 03:20
12F:→ OnlyRD: 构跟基底我打的 06/19 03:20
13F:→ OnlyRD: ,当然不想折磨别人。 06/19 03:20
14F:推 wulouise: 猜先有MSG_OBJ後有*_USE 然後有地方没改*_USE洞被乱补 06/19 08:27