I've just been reading up on type punning, strict aliasing and alignment and was having trouble understanding pointer alignment issues.
I know that there are exceptions when using char*
and was wondering if the following was safe to do:
char* test = malloc(sizeof(struct foo));
((struct foo*)test)->member = 10;
Apparently the safest way to do something like this would be to use memcpy
:
char* test = malloc(sizeof(struct foo));
struct foo A;
A.member = 10;
memcpy(test, &A, sizeof A);
But then what if you wanted to access/change those values:
((struct foo*)test)->member = 10;
If this wasn't safe to do due to pointer alignment then you would have to do 2 memcpy
s involving a tmp
variable?
struct foo tmp;
memcpy(&tmp, test, sizeof tmp);
tmp.member = 20;
memcpy(test, &tmp, sizeof tmp);
Surely this is more inefficient than a pointer cast? I'm not sure if all compilers would optimize out the memcpy
s.
For those wondering as to why you would want to do this, I was thinking that maybe you might want to store a char*
to a value of any type (yes I know you can use a union for this, but what if this was abstracted away so you would not be able to place your own types in said union).
And what about in the case that the char*
referred to an array of struct foo
.
for (size_t i = 0; i < size; ++i)
{
((struct foo*)test)[i].member = 10;
}
as opposed to:
for (size_t i = 0, j = 0; i < size; ++i, j += sizeof (struct foo))
{
struct foo tmp;
memcpy(&tmp, test + j, sizeof tmp);
tmp.member = 20;
memcpy(test + j, &tmp, sizeof tmp);
}