c define arrays in struct with different sizes
c, struct
Solution
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.
Problem
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){ ... ```