Let's see for ourselves!
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
void printhex(const void *pnt0, size_t s)
{
const unsigned char *pnt = pnt0;
while(s--) {
printf("%02x", *pnt++);
}
}
void printhexln(const char *pre, const void *pnt, size_t s, const char *post)
{
printf("%s", pre);
printhex(pnt, s);
printf("%s", post);
printf("\n");
}
struct Struct_1 {
unsigned int data1, data2;
};
struct Struct_2 {
unsigned int data3, data4;
};
int main()
{
// let's grab memory for 4 ints
size_t size = 4 * sizeof(int);
void * ptr = malloc(size);
assert(ptr != NULL);
// let's zero that memory
memset(ptr, 0, size);
// this will print zeros
printhexln("1: ", ptr, size, "");
( (struct Struct_1 *)ptr ) -> data1 = 0x1122;
printhexln("2: ", ptr, size, "");
( (struct Struct_1 *)ptr ) -> data2 = 0x3344;
printhexln("3: ", ptr, size, "");
( (struct Struct_2 *)ptr ) -> data3 = 0x5566;
printhexln("4: ", ptr, size, "");
( (struct Struct_2 *)ptr ) -> data4 = 0x7788;
printhexln("5: ", ptr, size, "");
free(ptr);
return 0;
}
will output on https://www.onlinegdb.com :
1: 00000000000000000000000000000000
2: 22110000000000000000000000000000
3: 22110000443300000000000000000000
4: 66550000443300000000000000000000
5: 66550000887700000000000000000000
printhex
is a simple function that prints the memory behind a pointer in hexadecimal characters. We can see that:
- first there are only zeros. We can count zeros and we see that
size = 16
and sizeof(int) = 4
.
- We then cast the pointer to struct Struct_1 and set data1 to 0x1122. The first 2 bytes of the pointer are overwritten and set to 0x2211, because the machine is little endian. The value of
((struct Struct_1)ptr)->data1
is now equal to 0x00001122
.
- We can see that writing 4433 to ((struct Struct_1*)pnt)->data2 sets byte 5 and 6 to 0x4433. Machine is little endian,
sizeof(int) = 4
and we can see that offsetof(struct Struct_1, data2) = 4
- Casting the struct to Struct_2 and writing to data3, overwrite first 2 bytes, not caring about the previous values. That's because
offsetof(struct Struct_2, data3) = 0
, so data3 starts at the beginning of the pointer.
- Well, 4433 is overwritten by 8877 when writing to the data4 member of Struct_2