0

I have an unsigned char* (bytes sent from the server) that I need to convert/cast to an array of structs whose size exactly matches that of the unsigned char*. Without copying values, how do I achieve this? In the uchar*, there could be any number of structs.

How do I achieve this?

I have tried the following (psuedo code):

// Define the struct:
struct MyStruct:
    unsigned char name[6]
    long time
    double speed

// ...some code...

// Get the uchar*.
unsigned char* chars = getUchars()

// The uchar*'s first byte is a special flag,
// so the structs start at index 1 not 0.
unsigned char* chars2 = &chars[1]

// Convert chars2 to an array of MyStructs.
MyStruct *structs = (MyStruct*) chars2

// Get the first struct and print values.
MyStruct s1 = structs[0]
_print(charArrayToString(s1.name), s1.time, s1.speed)
// When this _print() is called, the struct's
// name value is printed correctly, but its time
// and speed are not printed correctly.

// Get the second struct.
MyStruct s2 = structs[1]
_print(charArrayToString(s2.name), s2.time, s2.speed)
// None of this second struct's name, time and speed
// is printed correctly.

Where did I make mistakes?

4
  • 1
    long and double have alignment requirements. chars2 is probably not aligned correctly for them. Commented Dec 23, 2020 at 23:56
  • 2
    You may be able to solve it by using an implementation-specific option to make a packed structure. Commented Dec 23, 2020 at 23:57
  • 3
    Make a dump() function on your struct which dumps it byte-by-byte and also by data member. What you'll probably find is that there's some padding there that is causing problems. Commented Dec 23, 2020 at 23:58
  • 1
    Thank you for your responses. What do you mean by dump it byte by byte and by data member? Do you mean set the name, time and speed of each struct individually instead of casting the whole uchar2 directly to MyStruct*? Commented Dec 24, 2020 at 0:09

1 Answer 1

1

use pragma pack, it works in most compilers

#include <stdio.h>

struct DefaultPack
{
    char str[6];
    long time;
    double speed;
};

#pragma pack(push,1)
struct Packed
{
    char str[6];
    long time;
    double speed;
};
#pragma pack(pop)


int main (int argc, char *argv[])
{
    struct DefaultPack n;
    struct Packed p;
    printf("Sizes of struct:\n"
           "Default packing: %lu\n"
           "Packed: %lu\n"
           "in packed struct:\n"
           "offset of time: %lu\n"
           "offset of speed: %lu\n"
           "in default packed struct:\n"
           "offset of time: %lu\n"
           "offset of speed: %lu\n",
           sizeof(struct DefaultPack),
           sizeof(struct Packed),
           (void*)&p.time  - (void*)&p.str[0],
           (void*)&p.speed - (void*)&p.str[0],
           (void*)&n.time  - (void*)&n.str[0],
           (void*)&n.speed - (void*)&n.str[0]
           );
    return(0);
}
Sign up to request clarification or add additional context in comments.

1 Comment

------ output: Sizes of struct: Default packing: 24 Packed: 22 in packed struct: offset of time: 6 offset of speed: 14 in default packed struct: offset of time: 8 offset of speed: 16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.