@jonshouse, a quick 'tutorial' about this.
As @salem points out, this is about pointer arithmetic.
I thought it may be useful to see how that works in two primary forms.
First, to be clear at the risk of being pedantic, the raw block of memory passed the the function via data * is, at that point, declared to be char *'s, which are typically (99.9999999% of the time in modern code) 1 byte in size.
The format (presumably from your code, and likely a fact) is such that a struct jcp_header is first in this raw memory block, and it is followed by a struct dev_state.
The code posted here:
Code:
struct dev_state *ds = (struct dev_state *)(data+sizeof(struct jcp_header));
Works and is correct when data is a raw block of memory measured in bytes.
The type is what establishes that measurement. In this case, data is of type char *, where each char is 1 byte in length.
One of the primary purposes of pointer arithmetic is to advance through arrays. If a pointer is of type integer, and if integers are 4 bytes long, this would sequence through an integer array:
Code:
for( int * p = arrbase; p < limit; ++p ) { *p = 0; }
This naive code assumes arrbase in an int * to an array, and limit is an int * set to the end of the array. Every increment of p in this case moves the pointer forward by 4 bytes, because it is an integer type and integers are 4 bytes in this case.
If the compiler is configured for a different CPU where integers are 8 bytes, then p would be advanced 8 bytes for every increment for the same reason.
It is true, also, if p were a struct of some kind, such that an increment of p would advance the pointer by whatever the size of that struct is.
This brings me to this point:
Code:
struct jcp_header *jcp_ptr = ( struct jcp_header * ) data;
struct dev_state *devptr = (struct dev_state *) ( jcp_ptr +1 );
The parenthesis are important here. The second line is effectively the same as:
Code:
struct dev_state *ds = (struct dev_state *)&jcpheader[1];
Both forms treat jcpheader (or jcp_header *) as an array, and calculate the position of the next entry in that array, but then cast that to a dev_state *.
This is also the same thing as
Code:
struct dev_state *devptr = (struct dev_state *)( data + sizeof( struct jcp_header ) );
In this last case, however, data is a char *, so addition is based on the size of a char, making it work like standard addition.
In this example:
Code:
struct dev_state *devptr = (struct dev_state *) ( jcp_ptr + 1 );
The addition of 1 to jcp_ptr is based on the size of a jcp_header type, the sizeof( struct jcp_header).
If that were "jcp_ptr + 2", the pointer would have moved the size of 2 jcp_headers, and if it were "jcp_ptr + 3", it would have moved the size of 3 jcp_headers.
This is the same as jcp_ptr[1], jcp_ptr[2] or jcp_ptr[3].