On 2012-07-28, Maxim Fomin <> wrote:
> Problem: there is need to allocate space for some object of unknown
> quantity and I know, that in "99% cases" it would be less than N
> items. In such cases it is better to use fixed-size array, however I
> don't want to impose limitations and cover all possible cases (when
> quantity is bigger that N). As a trade-off I use union of fixed-size
> array with single element:
>
> union u
> {
> type *arr[N]; /* type is opaque structure */
> type *ptr;
> };
>
> If quantity is bigger than N, I assign allocated memory to ptr.
>
> However, consider following example program (uhack.c):
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> struct data
> {
> int val;
> char *align;
> } d0 = {0, "hello"},
> d1 = {1, "world"},
> d2 = {2, "from"},
> d3 = {3, "a"},
> d4 = {4, "simple"},
> d5 = {5, "c"},
> d6 = {6, "program"};
>
> union
> {
> struct data *arr[7];
> struct data *ptr;
> } u = {{&d0, &d1, &d2, &d3, &d4, &d5, &d6}};
>
> int main(void)
> {
> int i;
> struct data *new_ptr;
> for (i = 0; i < 7; i++) {
> printf("%s\n", u.ptr[i].align);
> }
> new_ptr = malloc(9 * sizeof *new_ptr);
> memcpy(new_ptr, u.ptr, 7 * sizeof *new_ptr);
> u.ptr = new_ptr;
> for (i = 0; i < 7; i++) {
> printf("%s\n", u.ptr[i].align);
> }
> return 0;
> }
Strange things happening here.
This program relies on the assumption that the variables
d0,d1,d2,d3,d4,d5,d6 are allocated contiguously and in that order.
The compiler is not obliged to honour this assumption.
See what happens when you swap, say, the lines
d1 = {1, "world"},
d2 = {2, "from"},
to get
d2 = {2, "from"},
d1 = {1, "world"},
In theory this should yield an equivalent program, but
you might find it changes the output printed by the program.
If, for whatever reason, the compiler decides to insert
padding between any of d0,d1,d2,d3,d4,d5,d6, the program
is likely to crash.
Note that the initialization
} u = {{&d0, &d1, &d2, &d3, &d4, &d5, &d6}};
is bogus (except for the initialization of the first element),
if the initialization were changed to, say,
} u = {{&d0, 0, 0, 0, 0, 0, 0}};
it would not change the working of the program, so why are
you taking the trouble to initialize u.arr[1..6] at all?