Re: [問題] C用結構指標操作資料的問題

看板C_and_CPP作者 (amoumou)時間5年前 (2018/12/14 15:39), 編輯推噓0(004)
留言4則, 2人參與, 5年前最新討論串2/2 (看更多)
※ 引述《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! -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.66.200.253 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1544773168.A.39A.html

12/16 22:46, 5年前 , 1F
1.從stack中分配sizeof(MY_DAT_STRUCT) 3.big/little Endia
12/16 22:46, 1F

12/16 22:47, 5年前 , 2F
Endian, 4.如果真的確定一樣的話, 我會用union
12/16 22:47, 2F

12/17 21:21, 5年前 , 3F
非常感謝!Endian真是要注意的重點;我也會改用Union,比
12/17 21:21, 3F

12/17 21:21, 5年前 , 4F
較能確定使用的是同一個空間。
12/17 21:21, 4F
文章代碼(AID): #1S4rumEQ (C_and_CPP)
文章代碼(AID): #1S4rumEQ (C_and_CPP)