Akay
Akay

Reputation: 1132

Copying a struct into a byte array

I have a 1-byte pragma packed struct in C which I want to copy into a byte array for serialization purpose to be sent over a serial port.

#pragma pack(push, 1)

typedef struct {
    uint8_t ck_a;
    uint8_t ck_b;
} UBXChecksum_t ;

#pragma pack(pop)

What is the best way of serializing it into a byte array, should I just use memcpy()?

void writeStructToArray(const void* inStruct,
                        const uint16_t inLenStruct,
                        uint8_t* const outArray)
{
  memcpy(outArray, inStruct, inLenStruct);
}

or better use byte-by-byte copying doing pointer typecasting?

void writeStructToArray(const void* inStruct,
                        const uint16_t inLenStruct,
                        uint8_t* const outArray)
{
  for(uint16_t i = 0; i < inLenStruct; i++)
  {
    outArray[i] = ((uint8_t*)inStruct)[i];
  }
}

Upvotes: 1

Views: 5039

Answers (2)

Bodo
Bodo

Reputation: 9855

As Kamil Cuk commented, your two proposals are nearly the same with some possible speed difference.

Another option would be to use a union:

typedef struct {
    uint8_t ck_a;
    uint8_t ck_b;
} UBXChecksum_t ;

union convert {
    UBXChecksum_t checksum;
    char buffer[sizeof UBXChecksum_t];
};

UBXChecksum_t checksum;

union convert converter;

converter.checksum = checksum;

passArrayToSomeFunction(converter.buffer, sizeof(converter.buffer));

You don't have to copy the data to convert it to an array. You could pass a pointer to the structure (if necessary casted to char* or void*) and the structure size to a function that sends the data to the serial port. Example:

typedef struct {
    uint8_t ck_a;
    uint8_t ck_b;
} UBXChecksum_t ;

int sendData(void *buf, size_t size);

UBXChecksum_t checksum;

/* ... */
int rc = sendData(&checksum, sizeof(checksum));

All these variants send the structure's internal representation as binary data. Normally "serializing" is understood as a way to convert the data into a platform-independent format.

Sending binary data structures works if the receiving system is of the same type and using the same compiler. You might get problems when the receiving system uses different byte order or different data type sizes.

In your case you have a structure of two uint8_t values, so the size is fixed and the byte order is not a problem.

It is OK to send binary data if the requirement for the structure is to match a specified binary data protocol and you are prepared to handle the byte order if necessary.

Upvotes: 5

Deepak
Deepak

Reputation: 96

memcpy() will not consider endiannsess of the system. so if Sender is big endian and receiver is little endian then then will be a conflict in the receiver for the structure variable value.

With the second method you know how the byte stream is prepared at sender so at the receiving end also it can receive accordingly to make sure of the proper structure variable value.

If the endianness of the systems is same and endianness is not a concern then both the method will serve the purpose and memcpy() will be faster compare to the assigning the byte value in a loop.

Upvotes: 1

Related Questions