void * assignment problem
I want to take some fields from packet struct using pointer arithmetic.But what is wrong with the code below ?
In first condition i think if i go 4 byte(2 short field) from beginning of packet i get tLow .But it does not give expected value.Additionally second case i want to get data field by going 12 byte from beginning of packet .What is wrong with my idea ?struct packet{
short len;
short field;
int tLow;
int tHigh;
void *dat开发者_开发知识库a;
}
int main()
{
struct packet pack;
struct packet *pck;
pack.len=3;
pack.field=34;
pack.tLow=712;
pack.tHigh = 12903;
pack.data = "message";
pck = &pack;
int *timeLow = (int * )pck + 4; // i want to get tLow
printf("Time Low :%d\n",*time);
char *msg = (char *)pck + 12 ;// want data
printf("Message :%s\n",msg);
return 0;
}
You definitely would be better using standard method
int *timeLow = &(pck->tLow);
Compilers are allowed to insert padding bytes between any member of a struct. The rules for these padding bytes are, at best, implementation defined ... so you must consult your implementation manual to be certain how (or if) and how many bytes are inserted in your specific case. Also note the number of padding bytes might change from compilation to compilation with different options or from compiler to compiler (computer to computer, ...)
You can try to use the C
macro offsetof
, but it's not pretty:
size_t offset = offsetof(struct packet, tLow);
/* make sure offset is a multiple of sizeof (int*) */
int *timeLow = (int*)pck + offset / sizeof (int*);
or, a little less ugly using a cast to (char*)
and copying the code from other answers :-)
size_t offset = offsetof(struct packet, tLow);
int *timeLow = (int*)((char*)pck + offset);
Oh! and there's a semi-colon missing in your source
Basically you are relying on undefined behavior. Struct alignment, etc. But anyways...
(int*)pck + 4. Will advance the pointer 4 * sizeof(int). This is wrong, we want to advance it by 1 if we assume that the struct is packed and sizeof(short) == 2, thus...
int *timeLow = (int * )pck + 1; // i want to get tLow
printf("Time Low :%d\n",*timeLow);
prints the correct result.
As for the message, you need to do some dirty stuff. Since I'm on x86_64 the compiler chose to pad the void* on 8 byte boundaries, so the offset was 16 rather than the expected 12.
We're basically fetching a pointer to a void*. So the code will look like this:
char **msg = (char**)((char *)pck + 16) ;// want data
printf("Message :%s\n",*msg);
NEVER write code like this, this just illustrates a point.
You are looking for offsetof.
Your code could look like this:
int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);
and as pmg pointed out,
int *timeLow = &(pck->tLow);
is the canonical way of getting a pointer to a member of a struct.
This answer also brought pointer arithmetics on the table - which I learned today thanks to pmg.
when you write
int *timeLow = (int * )pck + 4
you are treating 'pck' as a int pointer which depending on your system may be 4 or 8 bytes. That will not correctly offset into the struct because you are then telling it to have an offset of 4 int
instead you would need to do like this
int *timeLow = (int*)((short * )pck + 2);
Shorts are not necessarily 2 bytes long. All that is specified is that they are less-than or equal-to the size of ints. You should probably be using sizeof()
This is wrong: pack.data = "message";
You are using unallocated memory.
Also this: int *timeLow = (int * )pck + 4;
is not guaranteed to work (struct alignment varies between compilers and systems).
精彩评论