Вы не.
В C многомерные массивы - это массивы массивов, а не массив, где один элемент - это другой массив, а остальные - числа. int x[10][10]
объявляет x
как массив из 10 массивов по 10 int
с, то есть всего 100 элементов в матрице 10 x 10.
Чтобы сделать то, что вы описываете, вам понадобится массив void *
s:
struct myarr {
size_t len;
void **arr;
};
Вы выделяете len
элементов для arr
с x.arr = malloc(x.len * sizeof(void *))
. Тогда каждый элемент может быть чем угодно - возможно, числом, возможно, другим struct myarr
для дальнейшего вложения.
Однако на практике вы не сможете узнать, является ли void *
числом или другим массивом. Так что вам понадобится какая-то динамическая проверка типов.
enum mytype {
INT,
ARR,
};
Затем вы делаете struct myint
и повтор struct myarr
для совместимости:
struct myint {
enum mytype type;
int i;
};
struct myarr {
enum mytype type;
size_t len;
enum mytype **arr;
};
Когда вы делаете struct myint
, всегда устанавливайте x.type = INT
, а когда вы делаете struct myarr
, всегда устанавливайте x.type = ARR
.
struct
указатели всегда можно привести к указателю на первый элемент, поэтому и struct myint *
, и struct myarr *
можно привести к указателю enum mytype *
, который содержит ваш массив в myarr
. Затем, когда вы обращаетесь к элементу массива с помощью .arr[n]
, вы можете проверить (во время выполнения), какой тип он содержит, соответствующим образом привести указатель и использовать по желанию:
for(size_t i = 0; i < x.len, i++)
{
enum mytype *j = x.arr[i];
if(*j == INT)
{
printf("%i", ((struct myint *)j)->i);
}
else if(*j == ARR)
{
printf("[");
// recurse
printf("]");
}
else /* this should not happen, you messed up */;
}
Существуют и другие способы достижения того же самого.