user2578666
user2578666

Reputation: 1143

How does typecasting a char to a structure work

I have

 evnt_buff =  sSpiInformation.pRxPacket;
 data_to_recv = 0;
 hci_hdr = (hci_hdr_t *)(evnt_buff + sizeof(btspi_hdr));

My evnt_buff is 2. Now when I typecast the above data the hci_hdr

typedef struct _hci_hdr_t
{
    unsigned char ucType;
    unsigned char ucOpcode;
    unsigned char pad[3];
} hci_hdr_t;

hci_hdr->ucType has a value of 0. Is this the expected behaviour?

typedef struct _btspi_hdr
{
    unsigned char   cmd;
    unsigned short  length;
    unsigned char   pad[2];
}btspi_hdr;

My unsigned char *evnt_buff; is as defined . And why exacty is the sizeof() being added here?

The above piece of code gets called from another function. The other function initializes sSpiInformation.pRxPacket to point to a buffer whose first element is 2. This means that when

 evnt_buff =  sSpiInformation.pRxPacket; 

is executed it becomes equal to 2.

Another thing. Since I am porting the code from one compiler to another , in the first compiler #pragma pack(1) is used to declare all the structures. But since in my compiler I dont know the equivalent of that I simply removed that statement and initialized the structure without any packing. Could this be the issue?

Upvotes: 0

Views: 152

Answers (2)

Lundin
Lundin

Reputation: 213711

It is not clear what you mean or try to achieve You say that evnt_buff is a pointer to a character array where the first element is 2. If so, how does evnt_buff + sizeof(btspi_hdr) make any sense whatsoever?

Anyway, the bug is post likely related to struct padding. Every compiler has an option to turn off padding, if not #pragma pack then something else. Check the compiler documentation.

When you have questionable code like this, which relies on struct alignment, you should also add static compile-time checks to verify that no padding is enabled. One way to do so is to define a macro which yields a compiler error if the passed parameter is incorrect. For example:

#define static_assert (expr) {typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];}

(if you have a C11 compiler, a better static_assert is available by the compiler)

Then for every struct, type something like this:

static_assert (sizeof(btspi_hdr) == sizeof(cmd) +
                                    sizeof(length) +
                                    sizeof(pad) );

Upvotes: 0

alk
alk

Reputation: 70911

This line

hci_hdr = (hci_hdr_t *)(evnt_buff + sizeof(btspi_hdr));

implies that the memory pointed to by evnt_buff consists of

  1. an instance of btspi_hdr
  2. an instance of hci_hdr_t

So what the above line does is assigning to hci_hdr the address of that part of the memory pointed to by evnt_buff which represents the hci_hdr_t by adding the size of a btspi_hdr to evnt_buff.

From this I conclude hci_hdr is declared as hci_hdr_t *.

Upvotes: 1

Related Questions