stathis said:
Thank you for taking the time to do these corrections and i will take
that into account in the future.
Thank you.
/*For this example*/
member_size[0]=2;
member_size[1]=1;
Bad example. On many systems these days int is 4 bytes. You should be
using sizeof the appropriate variable.
True as well.
/*Fill in member_size array*/
for (count=0;count<struct_members;count++)
total_size+=member_size[count];
/*Allocate and fill in member_offset array*/
member_offset = malloc(struct_members*sizeof(*member_offset));
member_offset[0]=0;
for (count=1;count<struct_members;count++)
member_offset[count]=member_offset[count-1]+member_size[count];
So when count is 1 you get:
member_offset[1]=member_offset[0]+member_size[1]
which is
member_offset[1]=0+1
which is
member_offset[1]=1
When, since the fist element (according to you, but not if I built it on
any system I currently have access to) should be 2 to place it after the
first element instead of overlapping with it.
I did not fully understand this. I suppose this derives from the fact that i
supposed sizeif(int) is 2 in any system?
The fundamental problem in this part is nothing to do with the size of
an int.
In your code you store the size of the first item in member_size[0] and
its offset (which is 0) in member_offset[0]. Given that the first member
takes two bytes, that would be a[0] and a[1]. So to calculate the
position of the second item you need to take the offset of the first
item and add the size of the first item, where as you were adding the
size of the second item. I.e., you should have:
member_offset[count]=member_offset[count-1]+member_size[count-1];
/*Print for test purposes*/
printf("Integer is: %d\n",*(a+member_offset[0]));
printf("Character is: %c\n",*(a+member_offset[1]));
This, in the general case, will not work, since you are completely
ignoring alignment requirements. If using this type of approach you have
to use memcpy to copy the data out in to a suitable variable data
(except for character types) before using it.
I see, will that generally work instead:
"printf("Integer is: %d\n", *((int *)(a+member_offset[0])));" ? Please shed
some more light on this.
Actually, I've just realised that I had miss-read what you initially
posted, so what I said it not actually quite true, although there was
still a problem.
Your original line:
printf("Integer is: %d\n",*(a+member_offset[0]));
will print one byte of the first member, since a is an array of char.
Obviously this is not what you want.
Your suggestion of
printf("Integer is: %d\n", *((int *)(a+member_offset[0])));
has potentially bigger problems.
Some real systems have alignment requirements for various types, so if
you try to read a 2 byte integer from an odd address they will generate
an error (often called a "bus error" or SIGBUS) and abort your program.
Since as far as the compiler is concerned a is an array of char (and
char does not have any alignment requirements) a could start on an odd
address. So casting it to an int* then dereferencing it could crash your
program (the C standard allows this).
So what you have to do is the reverse of when you put the data in. I.e.:
memcpy(i, a+member_offset[0], member_size[0]);
printf("Integer is: %d\n", i);
Ideally you should add at least basic error trapping, i.e.
if (member_size[0] != sizeof i)
fputs("ERROR: Size miss-match!\n");
else {
memcpy(i, a+member_offset[0], member_size[0]);
printf("Integer is: %d\n", i);
}