Re: safe "struct hack"?
On 14.08.13 15.45, Jonathan Lee wrote:
struct header
{
int a;
int b;
double c;
// int arr[]; // I think C99 would do this
Does this no longer work?
I could bet I have used this from time to time.
}
;
Then I can make the union
union wrap
{
header hdr;
int arr[1];
}
;
Do you really want to have a union here? I.e. you either have a header
/or/ one integer?
And use calloc to get some memory
void* p = calloc(20, sizeof(wrap));
You are allocating 20 headers here. There is no (portable) implication
on the number of additional integers. I would have expected something like
calloc(1, sizeof(wrap) + 20 * sizeof(int))
The following casts should be legal:
union* u = static_cast<union*>(p);
union is no type. You mean wrap.
header* h = static_cast<header*>(u);
Wrong. You cannot use static_cast for unrelated types.
Do you mean header* h = &u->hdr; ?
int* i = static_cast<int*>(u);
Also wrong for the same reason.
But, then, this should also be legal
int* j = static_cast<int*>(u + 1);
Same here. Here you need reinterpret_cast.
which is an aligned int pointer just past the header
struct. Seeing as how this came from calloc-d, "void"
memory, I think j + 0, j + 1, j + 2, ... are legal
int addresses.
You can't exactly know how many of them are legal. Se above.
After all, I can legally use
int* q = static_cast<int*>(p);
This works syntactically, as p is void*.
as an int array. I don't see why j would be any
different.
It is entirely different. p points to the start of your storage, while j
points after the (first) header.
Use
printf("p=%p\nu=%p\nh=%p\ni=%p\nj=%p\nq=%p\n", p,u,h,i,j,q);
to see what's going on.
Whatever you are going to do here seems not to hit the nail on the head.
If you want to have an header and a dynamically sized integer array in
one allocation then write a class with a custom new operator that takes
an additional argument for the size of the array and provide functions
for more or less safe access to the array. At least in debug builds I
would recommend boundary checks.
Marcel