Reputation: 83
here I want to read data from input to struct dev, so I am using temp = (dev*) input to casting from char* to dev*. On my machine,the line printf("%p\n", temp); prints out 0x804a040, and if is true the line printf("%p\n", temp+1); should prints out 0x804a04b, but it printed 0x804a04c. the line printf("%p\n", &temp->size); should prints out 0x804a047, but it printed 0x804a048.
Plz help me figure out what I misunderstand or incorrect
@all: thanks all for your helping. I got it. I've read some post and solusion is using #paragma pack(1) or some directive like this. but it also is discourage because it will slow the processing of precessor. So, is there any other ideas for this.
Thank!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct dev
{
short id;
char name[5];
int size;
} dev;
char input[] = { 0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x09, 0x00, 0x00, 0x00,
0x00, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00,
0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00,
0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00 };
int
main (int argc, char *argv[])
{
dev* temp;
temp = (dev*)input;
printf("%p\n", temp);
printf("%p\n", temp+1);
printf("%d\n", temp->id);
printf("%p\n", &temp->name[4]);
printf("%p\n", &temp->size);
temp++;
printf("%d\n", temp->id);
return 0;
}
Upvotes: 0
Views: 4955
Reputation: 3379
temp+1
should hold where the next dev should be. Here sizeof(dev)
is 12 so temp +1
should basically be at 0x804a04c
because (0x804a040-0x804a04b)
is reserved for first dev.
The size is 12 because for optimization you compiler allocated memory in multiple of 4. This is a typical optimization technique in 32 bit architecture. Actually your memory allocation is most probably ike:
<char><char><char><char>
<char><short><padding>
<int>
With total size of 12
Upvotes: 0
Reputation: 11536
You've presumed that the compiler has assembled your struct with no padding. Check sizeof(dev)
and it won't be what you think it is.
The purpose of the padding is to align int member fields on word (4-byte) boundaries -- since a short is 2 and "name" is five, you have one byte of padding between name
and size
.
One solution is to make name
6 bytes. This is no guarantee that some weird compiler won't do something strange -- but that seems unlikely. You can also use compiler specific "pack" pragmas.
The best solution would probably be to copy-map the input to the fields individually.
Upvotes: 0
Reputation: 7044
typedef struct dev
{
short id;
char name[5];
int size;
} dev;
Is probably not aligned the way you think it is. There is compiler dependent padding between the fields. Google "struct padding" or something like that.
This should show you the field offsets:
dev foo;
printf("offset of id is %d\n", (char *)&foo.id - (char *)&foo);
printf("offset of name is %d\n", (char *)&foo.name[0] - (char *)&foo);
printf("offset of size is %d\n", (char *)&foo.size - (char *)&foo);
Upvotes: 3
Reputation: 4369
answer is very simple: sum of sizes of each of your struct's item is 11 bytes, but for performance reasons 'int size' is placed to adress divisible by 4.
So 'size's offset in struct should be 7 but is 8 (as 8 is the closer number divisible by 4), so final size is 12.
You can force compiler to pack struct. For gcc you can do it like this:
typedef struct dev
{
short id;
char name[5];
int size;
} dev __attribute__ ((packed));
Upvotes: 1
Reputation: 124632
Alignment. Data will often be aligned on word size boundaries as it is the "natural" size for a processor to read and improves performance.
In this case, the size of your structure is 11 bytes. It is padded to 12.
Upvotes: 0