Reputation: 4841
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 array sizes are different in the two types, one using SIZE_A, the other SIZE_B.
Duplicating the definition of the struct and functions is not wanted.
How could I use one type of 'struct', and initialize its arrays with different sizes?
#define SIZE_A 100
#define SIZE_B 200
typedef struct{
int matr[SIZE_A][SIZE_A]; // for another type matr[SIZE_B]
int arr[SIZE_A]; // for another type arr[SIZE_B]
int size; // will be initialized to SIZE_A or SIZE_B
int var1, var2;
}s;
void task1(s* si){
...
}
void task2(s* si){
...
Upvotes: 4
Views: 4532
Reputation: 70502
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.
Upvotes: 2
Reputation: 5168
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.
Upvotes: 1
Reputation: 11143
Even with a union, the struct will be as big as the largest of the two arrays.
Do one of these:
malloc
.Upvotes: 5