Access struct as array of bytes

2019-04-13 00:00发布

I'm currently in the process of re-writing a program to process data received over a serial connection using the RDM protocol, each packet is received by a UART and has a specific structure but may vary in length, a packet structure example is below, assuming the number of bytes in the packet to be n (this may change depending on the contents of the packet)

What I want to do is define a struct in my C code that has the various parameters defined, but to be able to read and write bytes to/from the struct from the UART as though the struct is just an array of uint8_t. My issue with this is that I have read that structs may not always be stored in continuous sections of memory, so taking &RDMPacket1 and increment through the struct may end up with the data not being in the right place.

My other problem is that if I have an array to store a packet data of the maximum possible length (220 bytes) inside the struct, then the checksum at the end of the packet would be written into the wrong place. What methods could be used to receive the data and place it into the struct?

Example packet definition (shortened from standard)

Byte     | Description
0        | START Code - Constant, can be ignored
1        | Sub-Start Code - Contains command for device to process
2        | Message Length - Points to byte number of Checksum High (up to 255)
3-8      | Destination UID - Unique ID of packet Destination
9-14     | Source UID - Unique ID of packet Source
15       | Transaction Number - ID of transaction between controller and responder
16-(n-2) | Data (up to 220 bytes long)
n-1      | Checksum High
n        | Checksum Low

This is an example of a struct to hold the a packet of maximum possible length:

struct RDMPacket
{
    uint8_t     subStartCode;
    uint8_t     messageLength;
    uint32_t    destinationUID;
    uint32_t    sourceUID;
    uint8_t     transactionNumber;
    uint8_t     portID;
    uint8_t     messageCount;
    uint8_t     subDevice;
    uint8_t     commandClass
    uint8_t     parameterID;
    uint8_t     parameterDataLength;
    uint8_t     parameterData[220];
    uint16_t    checksum
} RDMPacket1;

1条回答
乱世女痞
2楼-- · 2019-04-13 00:27

The problem that you are describing can arise when you are dealing with a non-byte aligned memory structure. In this case each struct field will have the specific alignment. I.e., if the alignment is 4 bytes, each field will start on an address that is divisible by 4. To avoid this, you can use GCC's attribute packed for the structure, that instructs the compiler to pack the structure to a minimal memory. In other compilers there is #pragma pack or some other corresponding compiler directives for this purpose. To make sure that your struct is packed, you can check it's size with sizeof and compare it to the expected size.

查看更多
登录 后发表回答