Re: [问题] C用结构指标操作资料的问题

楼主: amoumou (amoumou)   2018-12-14 15:39:26
※ 引述《amoumou (amoumou)》之铭言:
: 开发平台(Platform):
: 我是在32Bit Renesas MCU上实作
: 我想要用结构指标来操作资料例如:
: // MSB bit7 - bit0 LSB
: // 要用来操作的结构
: typedef struct
: {
: uint8_t JoystickUpStatus:1;
: uint8_t JoyStickLeftStatus:1;
: uint8_t JoyStickRightStatus:1;
: uint8_t JoyStickDownStatus:1;
: uint8_t Pending1:4;
: uint16_t TimeCounter1:12;
: uint8_t Pending2:4
: uint16_t SpeedValue:16;
: uint8_t XStatus:2;
: uint8_t YStatus:2;
: uint8_t Pending3:2;
: uint16_t TimeCounter2:10;
: uint8_t Pending4:8;
: }MY_DAT_STRUCT; //8 bytes, 64bit total
: uint64_t TX_DATA = 0xF0CCF03FFE000008; //通常资料一次送8 bytes出去
: MY_DAT_STRUCT *my_dat_struct = (MY_DAT_STRUCT *)&TX_DATA;
: //以下为预期结果
: my_dat_struct->JoystickDownStatus 数值为 1;
: my_dat_struct->SpeedValue 数值为 0x3FFE;
: my_dat_struct->TimeCounter2 数值为 0xCCC;
: 实际跑出来结果跟预期相符。
: 这样做的目的是希望增加程式的可读性,能明确的知道哪些bit是做什么用的;
: 在读取的时候也能快速的取出要的数值。
: 我想问的问题是(我的lib中没有sizeof()可以用):
: 1. 若我宣告 MY_DAT_STRUCT my_dat; my_dat的size会是连续的64bits吗?
: 2. 承上,若宣告为 *my_dat; 那么size应该会是多少?
: 3. TX_DATA透过转型成结构指标操作的话,会不会有潜在的问题(例如没对齐)?
: 4. 这样的作法(转型操作)是正确/常见的使用方式吗?
我做了一些测试跟爬文找到一些解答了。
首先上篇文章写到的实际跑出来的结果跟预期相符是错误的,实际上位置偏移了。
原本我预期MY_DAT_STRUCT的Size应该是8 Bytes, 但实际上却是10 Bytes,这与对齐的设定有关。
实际读取变成
JoyStickRightStatus = 0
JoyStickLeftStatus = 0
JoyStickRightStatus = 0
JoyStickDownStatus = 1
Pending1 = 0
TimeCounter1 = 0xE00
Pending2 = 0xf
SpeedValue = 0xF03F
XStatus = 0
YStatus = 0x3
Pending3 = 0
TimeCounter2 = 0x3C3
Pending4 = 0x5C
会造成这样的结果主要是没有设定对齐或是资料的排列没有最佳化,这个例子里因为没设定对齐方式,
默认会是自然对齐,也就是他会用结构内最大的uint16_t, 2bytes来对齐。
若我使用#pragma pack(1) 让他用 1Byte来对齐就会是我预期的 8 Bytes大小了。
要设定对齐我所知的有两种方式
1. 设定complier
2. 用#pragma pack(n)
关于我的第3个问题,我认为只要资料与结构的size及范围相符,用结构指标操作应该是没问题的。
第1及第4个问题我就不确定了;才疏学浅,以上若有错误的地方还拜托大家指正了,Thanks!
作者: kokal (细菌)   2018-12-16 22:46:00
1.从stack中分配sizeof(MY_DAT_STRUCT) 3.big/little EndiaEndian, 4.如果真的确定一样的话, 我会用union
楼主: amoumou (amoumou)   2018-12-17 21:21:00
非常感谢!Endian真是要注意的重点;我也会改用Union,比较能确定使用的是同一个空间。

Links booklink

Contact Us: admin [ a t ] ucptt.com