I'm trying to create multiple structs in C with one "base" struct type representing multiple types of objects:
#include <stdio.h>
#include <sys/types.h>
enum parent_type{
parent_type_1,
parent_type_2
};
struct Child{
int size_bytes;
};
struct Parent1{
struct Child base;
u_int16_t val;
};
struct Parent2{
struct Child base;
u_int8_t val;
};
void readParentData(struct Child* toread){
printf("Byte size: %d\n", toread->size_bytes);
int val_read = *((u_int16_t*)((&toread) sizeof(struct Child)));
printf("Value: %d\n", val_read);
}
struct Parent1 p1;
int main(){
p1.val = 1000;
p1.base.size_bytes = 2;
struct Parent1* p1_p = &p1;
struct Child* child_p = (struct Child*)p1_p;
readParentData(child_p);
}
I would expect readParentData() to output 1000, but instead it is outputting random values. I get the correct output if i cast the pointer to a Parent1 pointer:
printf("Cast value: %d\n", ((struct Parent1*)(toread))->val);
but this won't work if I have to use the function for other structs, like Parent2.
I've also tried using the offsetof() function but that gives the same result as my original pointer arithmetic:
int val_read = *((u_int16_t*)((&toread) offsetof(struct Parent1, val)));
I would expect that adding the size of a struct to its pointer gives the address of the next values in the "Parent" struct, but this is apparently not the case.
CodePudding user response:
((&toread) sizeof(struct Child)))
is offsetting the address of toread
by sizeof(struct Child)
. You need to offset what toread
points to by sizeof(struct Child)
. Additionally, offsetting toread
by sizeof(struct Child)
adds sizeof(struct Child) * sizeof(struct Child)
to toread
. To offset toread
by the size of 1 child, you need to add 1 to it.
What you need to do for this to work is
void readParentData(struct Child* toread){
printf("Byte size: %d\n", toread->size_bytes);
int val_read = *((u_int16_t*)(toread 1));
printf("Value: %d\n", val_read);
}
But this is not a good way to do it. If you want to read the parent data, you should just cast the pointer to a struct Parent1*
and read it directly
void readParentData(struct Child* toread){
printf("Byte size: %d\n", toread->size_bytes);
int val_read = ((struct Parent1*)(toread))->val;
printf("Value: %d\n", val_read);
}