I need to define a struct for two types of objects. Both have exactly the same data structure and perform same tasks (member methods).
The ONLY difference is that the a
Even with a union, the struct will be as big as the largest of the two arrays.
Do one of these:
malloc
.I would make matr
a flexible array at the end of your struct. Then, I would stick the arr
array into the last row of matr
.
typedef struct {
int size;
int var1, var2;
int matr[];
} s;
static inline int size_ok_s (int size) {
switch (size) {
case SIZE_A:
case SIZE_B:
return 1;
default:
break;
}
return 0;
}
s * create_s (int size) {
s *x = 0;
if (size_ok_s(size)) {
x = malloc(sizeof(*x) + sizeof(int[size+1]));
if (x) x->size = size;
}
return x;
}
To achieve a uniform interface, you can use a macro:
#define s_matr(x) ((int (*)[(x)->size])(size_ok_s((x)->size) ? (x)->matr : 0))
#define s_arr(x) (s_matr(x)[(x)->size])
So, to access the i
th row and j
th column of s *foo
's matr
, and its k
th element of arr
:
s *foo = create_s(SIZE_A);
/* ... */
s_matr(foo)[i][j] = 0;
s_arr(foo)[k] = 0;
Flexible array members are a new feature of C.99 described in §6.7.2.1 ¶16. Prior to C.99, C programmers often used what was known as the struct
hack:
typedef struct {
int size;
int var1, var2;
int matr[1];
} s;
s * create_s (int size) {
s *x = 0;
if (size_ok_s(size)) {
x = malloc(sizeof(*x) + sizeof(int[size]));
if (x) x->size = size;
}
return x;
}
This is a hack since in C.89-90, indexing the matr
array with a value greater than 0
is technically accessing an object beyond its boundary. However, it was a common practice, and widely portable. C.99 formally sanctioned the mechanism with the flexible array member, although it requires the syntax of not specifying a size in the array declaration.
Have the arrays be pointers and allocate to them (the appropriate size) as needed. Only downsize is access to the 2D array will be a little clumsy.