Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typecast array to struct in c

Tags:

c

structure

I have a structure like this

struct packet
{
int seqnum;
char type[1];
float time1;
float pri;
float time2;
unsigned char data[512];
}

I am receiving packet in an array

char buf[529];

I want to take the seqnum,data everything separately.Does the following typecast work.. It is giving junk value for me.

struct packet *pkt;
pkt=(struct packet *)buf;
printf(" %d",pkt->seqnum)
like image 583
user1762571 Avatar asked Apr 15 '13 14:04

user1762571


3 Answers

No, that isn't generally valid code. You should make the struct first and then memcopy stuff into it:

packet p;

memcpy(&p.seqnum, buf + 0, 4);

memcpy(&p.type[0], buf + 4, 1);

memcpy(&p.time1, buf + 5, 4);

And so forth.

You must take great care to get the type sizes and endianness right.

like image 40
Kerrek SB Avatar answered Sep 18 '22 11:09

Kerrek SB


No, that likely won't work and is generally a bad and broken way of doing this.

You must use compiler-specific extensions to make sure there's no invisible padding between your struct members, for something like that to work. With gcc, for instance, you do this using the __attribute__() syntax.

It is, thus, not a portable idea.

It's much better to be explicit about it, and unpack each field. This also gives you a chance to have a well-defined endianness in your network protocol, which is generally a good idea for interoperability's sake.

like image 105
unwind Avatar answered Sep 18 '22 11:09

unwind


First of all, you cannot know in advance where the compiler will insert padding bytes in your structure for performance optimization (cache line alignment, integer alignment etc) since this is platform-dependent. Except, of course, if you are considering building the app only on your platform.

Anyway, in your case it seems like you are getting data from somewhere (network ?) and it is highly probable that the data has been compacted (no padding bytes between fields).

If you really want to typecast your array to a struct pointer, you can still tell the compiler to remove the padding bytes it might add. Note that this depends on the compiler you use and is not a standard C implementation. With gcc, you might add this statement at the end of your structure definition :

struct my_struct {
    int blah;
    /* Blah ... */
} __attribute__((packed));

Note that it will affect the performance for member access, copy etc ...

Unless you have a very good reason to do so, don't ever use the __attribute__((packed)) thing !

The other solution, which is much more advisable is to make the parsing on your own. You just allocate an appropriate structure and fill its fields by seeking the good information from your buffer. A sequence of memcpy instructions is likely to do the trick here (see Kerrek's answer)

like image 25
Rerito Avatar answered Sep 20 '22 11:09

Rerito