Is it possible to allocate memory that's enough to hold only a specific union member? I mean something like this:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
union u;
union u{
int a;
long b[4096];
};
int main(){
union u tmp = {.a = 42};
union u *u = (union u*) malloc(sizeof(int)); //not malloc(sizeof(union u))
memcpy(u, &tmp, sizeof(int));
printf("u::a = %lu\n", u -> a);
}
sizeof(union u) equals to sizeof(long[4096]) and it would be wasting of memory to allocate 4096 * sizeof(long) to hold a single int.
Is it possible to do such a thing like the one above? Or is it undefined behavior?
I found the answer why it is invalid usage of union. N1570::6.2.5p(20):
A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type.
It means the union object must have enough memory allocated to hold each member of the union, but it's overlapping. In my case it is not legal use of union since I allocated memory enough to hold only one of them.
Is it possible to allocate memory that's enough to hold only a specific union member?
Yes. Yet code must then not attempt to use members in the unallocated parts.
For clarity, the below uses union ab rather than union u.
Initial part of code: no issues.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
union ab;
union ab {
int a;
long b[4096];
};
int main(){
union ab tmp = {.a = 42};
Assigning a pointer to scant memory is not an issue unto itself. Although for cast is not needed and I find allocating to the size of the object/member more informative (easier to code, review and maintain) than allocating to the size of the type.
// union ab *u = (union ab*) malloc(sizeof(int)); //not malloc(sizeof(union ab))
union ab *u = malloc(sizeof u->a);
The copying/assignment has no problems as the memory pointed to by u is sufficient.
memcpy(u, &tmp, sizeof(int));
// or
u.a = tmp.a;
Printing is a problem as code is using a mis-matched specifier. On the corrected code, no issue in accessing the member .a
// printf("ab::a = %lu\n", u -> a);
printf("ab::a = %d\n", u->a);
So far no problems.
Some new code is a problem as code attempts to read via u, outside allocated memory - this is undefined behavior (UB).
temp = *u;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With