简体   繁体   中英

How can I access members of a struct when it's not aligned properly?

I'm afraid that I'm not very good at low level C stuff, I'm more used to using objects in Obj-c, so please excuse me if this is an obvious question, or if I've completely misunderstood something...

I am attempting to write an application in Cocoa/Obj-C which communicates with an external bit of hardware (a cash till.) I have the format of the data the device sends and receives - and have successfully got some chunks of data from the device.

For example: the till exchanges PLU (price data) in chunks of data in the following format: (from the documentation)

Name Bytes Type

Name             Bytes    Type

PLU code h        4      long   
PLU code L        4      long
desc              19     char
Group             3      char
Status            5      char 
PLU link code h   4      long 
PLU link code l   4      long
M&M Link          1      char
Min. Stock.       2      int
Price 1           4      long 
Price 2           4      long

Total 54 Bytes

So I have a struct in the following form in which to hold the data from the till:

typedef struct MFPLUStructure { 
 UInt32   pluCodeH; 
 UInt32   pluCodeL; 
 unsigned char description[19]; 
 unsigned char group[3]; 
 unsigned char status[5]; 
 UInt32   linkCodeH; 
 UInt32   linkCodeL; 
 unsigned char mixMatchLink; 
 UInt16   minStock; 
 UInt32   price[2];  
} MFPLUStructure;  

I have some known sample data from the till (below) which I have checked by hand and is valid

00 00 00 00 4E 61 BC 00 54 65 73 74 20 50 4C 55 00 00 00 00 00 00 00 00 00 00 00 09 08 07 17 13 7C 14 04 00 00 00 00 09 03 00 00 05 BC 01 7B 00 00 00 00 00 00 00

ie

  • bytes 46 to 50 are <7B 00 00 00> == 123 as I would expect as the price is set to '123' on the till.

  • byte 43 is <05> == 5 as I would expect as the 'mix and match link' is set to 5 on the till.

  • bytes 39 to 43 are <09 03 00 00> == 777 as I would expect as the 'link code' is set to '777' on the till.

  • Bytes 27,28,29 are <09 08 07> which are the three groups (7,8 & 9) that I would expect.

The problem comes when I try to get some of the data out of the structure programmatically: The early members work correctly right up to, and including the five 'status' bytes. However, members after that don't come out properly. (see debugger screenshot below.)

Image 1 - http://i.stack.imgur.com/nOdER.png

I assume that the reason for this is because the five status bytes push later members out of alignment - ie they are over machine word boundaries. Is this right?

Image 2 - i.imgur.com/ZhbXU.png

Am I right in making that assumption?
And if so, how can I get the members in and out correctly?

Thanks for any help.

Either access the data a byte at a time and assemble it into larger types, or memcpy it into an aligned variable. The latter is better if the data is known to be in a format specific to the host's endianness, etc. The former is better if the data follows an external specification that might not match the host.

If you're sure that endianness of host and wire agree, you could also use a packed structure to read the data in a single pass. However, this is compiler-specific and will most likely impact performance of member access.

Assuming gcc , you'd use the following declarations:

struct __attribute__ ((__packed__)) MFPLUStructure { ... };
typedef struct MFPLUStructure MFPLUStructure;

If you decide to use a packed structure, you should also verify that it is of correct size:

assert(sizeof (MFPLUStructure) == 54);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM