Да
В вызове A необходимо указать количество измерений и указать размер каждого измерения. Используя немного C99:
код
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
extern void A(int *base, int ndims, ...);
extern void B(void);
void A(int *base, int ndims, ...)
{
assert(ndims > 0);
int dims[ndims];
int size = 1;
va_list args;
va_start(args, ndims);
for (int i = 0; i < ndims; i++)
{
dims[i] = va_arg(args, int);
size *= dims[i];
}
va_end(args);
int mods[ndims];
// I suspect this 'mods' loop is suboptimal, but it works.
for (int i = 0; i < ndims; i++)
{
int v = size;
for (int j = 0; j <= i; j++) {
v /= dims[j];
mods[i] = v;
}
}
for (int offset = 0; offset < size; offset++)
{
printf("%s", "array");
for (int i = 0; i < ndims; i++)
{
int p = offset / mods[i];
printf("[%d]", p % dims[i]);
}
printf(" = %d\n", base[offset]);
}
}
void B(void)
{
enum { dim1 = 4, dim2 = 6 };
int array1[dim1][dim2] =
{
{ 0, 1, 2, 3, 4, 5 },
{ 22, 21, 20, 19, 18, 17 },
{ 32, 31, 30, 39, 38, 37 },
{ 42, 41, 40, 49, 48, 47 },
};
int array2[dim2][dim1][dim2] =
{
{
{ 15, 68, 67, 16, 105, 4 },
{ 25, 58, 67, 16, 115, 4 },
{ 35, 48, 67, 16, 125, 4 },
{ 45, 38, 67, 16, 135, 4 },
},
{
{ 19, 69, 77, 16, 205, 5 },
{ 29, 59, 77, 16, 215, 5 },
{ 39, 49, 77, 16, 225, 5 },
{ 49, 39, 77, 16, 235, 5 },
},
{
{ 12, 64, 87, 16, 305, 6 },
{ 22, 54, 87, 16, 315, 6 },
{ 32, 44, 87, 16, 325, 6 },
{ 42, 34, 87, 16, 335, 6 },
},
{
{ 17, 63, 97, 16, 405, 7 },
{ 27, 53, 67, 16, 415, 7 },
{ 37, 43, 97, 16, 425, 7 },
{ 47, 33, 97, 16, 435, 7 },
},
{
{ 10, 60, 90, 10, 500, 97 },
{ 20, 50, 60, 20, 510, 87 },
{ 30, 40, 90, 30, 520, 77 },
{ 40, 30, 90, 40, 530, 67 },
},
{
{ 11, 63, 97, 36, 605, 39 },
{ 21, 53, 67, 46, 615, 38 },
{ 31, 43, 97, 56, 625, 27 },
{ 41, 33, 97, 66, 635, 26 },
},
};
A(&array1[0][0], 2, dim1, dim2);
putchar('\n');
A(&array2[0][0][0], 3, dim2, dim1, dim2);
}
int main(void)
{
B();
return(0);
}
Пример вывода
array[0][0] = 0
array[0][1] = 1
array[0][2] = 2
array[0][3] = 3
array[0][4] = 4
array[0][5] = 5
array[1][0] = 22
array[1][1] = 21
array[1][2] = 20
array[1][3] = 19
array[1][4] = 18
array[1][5] = 17
array[2][0] = 32
array[2][1] = 31
array[2][2] = 30
array[2][3] = 39
array[2][4] = 38
array[2][5] = 37
array[3][0] = 42
array[3][1] = 41
array[3][2] = 40
array[3][3] = 49
array[3][4] = 48
array[3][5] = 47
array[0][0][0] = 15
array[0][0][1] = 68
array[0][0][2] = 67
array[0][0][3] = 16
array[0][0][4] = 105
array[0][0][5] = 4
array[0][1][0] = 25
array[0][1][1] = 58
array[0][1][2] = 67
array[0][1][3] = 16
array[0][1][4] = 115
array[0][1][5] = 4
array[0][2][0] = 35
array[0][2][1] = 48
array[0][2][2] = 67
array[0][2][3] = 16
array[0][2][4] = 125
array[0][2][5] = 4
array[0][3][0] = 45
array[0][3][1] = 38
array[0][3][2] = 67
array[0][3][3] = 16
array[0][3][4] = 135
array[0][3][5] = 4
array[1][0][0] = 19
array[1][0][1] = 69
array[1][0][2] = 77
array[1][0][3] = 16
array[1][0][4] = 205
array[1][0][5] = 5
array[1][1][0] = 29
array[1][1][1] = 59
array[1][1][2] = 77
array[1][1][3] = 16
array[1][1][4] = 215
array[1][1][5] = 5
array[1][2][0] = 39
array[1][2][1] = 49
array[1][2][2] = 77
array[1][2][3] = 16
array[1][2][4] = 225
array[1][2][5] = 5
array[1][3][0] = 49
array[1][3][1] = 39
array[1][3][2] = 77
array[1][3][3] = 16
array[1][3][4] = 235
array[1][3][5] = 5
array[2][0][0] = 12
array[2][0][1] = 64
array[2][0][2] = 87
array[2][0][3] = 16
array[2][0][4] = 305
array[2][0][5] = 6
array[2][1][0] = 22
array[2][1][1] = 54
array[2][1][2] = 87
array[2][1][3] = 16
array[2][1][4] = 315
array[2][1][5] = 6
array[2][2][0] = 32
array[2][2][1] = 44
array[2][2][2] = 87
array[2][2][3] = 16
array[2][2][4] = 325
array[2][2][5] = 6
array[2][3][0] = 42
array[2][3][1] = 34
array[2][3][2] = 87
array[2][3][3] = 16
array[2][3][4] = 335
array[2][3][5] = 6
array[3][0][0] = 17
array[3][0][1] = 63
array[3][0][2] = 97
array[3][0][3] = 16
array[3][0][4] = 405
array[3][0][5] = 7
array[3][1][0] = 27
array[3][1][1] = 53
array[3][1][2] = 67
array[3][1][3] = 16
array[3][1][4] = 415
array[3][1][5] = 7
array[3][2][0] = 37
array[3][2][1] = 43
array[3][2][2] = 97
array[3][2][3] = 16
array[3][2][4] = 425
array[3][2][5] = 7
array[3][3][0] = 47
array[3][3][1] = 33
array[3][3][2] = 97
array[3][3][3] = 16
array[3][3][4] = 435
array[3][3][5] = 7
array[4][0][0] = 10
array[4][0][1] = 60
array[4][0][2] = 90
array[4][0][3] = 10
array[4][0][4] = 500
array[4][0][5] = 97
array[4][1][0] = 20
array[4][1][1] = 50
array[4][1][2] = 60
array[4][1][3] = 20
array[4][1][4] = 510
array[4][1][5] = 87
array[4][2][0] = 30
array[4][2][1] = 40
array[4][2][2] = 90
array[4][2][3] = 30
array[4][2][4] = 520
array[4][2][5] = 77
array[4][3][0] = 40
array[4][3][1] = 30
array[4][3][2] = 90
array[4][3][3] = 40
array[4][3][4] = 530
array[4][3][5] = 67
array[5][0][0] = 11
array[5][0][1] = 63
array[5][0][2] = 97
array[5][0][3] = 36
array[5][0][4] = 605
array[5][0][5] = 39
array[5][1][0] = 21
array[5][1][1] = 53
array[5][1][2] = 67
array[5][1][3] = 46
array[5][1][4] = 615
array[5][1][5] = 38
array[5][2][0] = 31
array[5][2][1] = 43
array[5][2][2] = 97
array[5][2][3] = 56
array[5][2][4] = 625
array[5][2][5] = 27
array[5][3][0] = 41
array[5][3][1] = 33
array[5][3][2] = 97
array[5][3][3] = 66
array[5][3][4] = 635
array[5][3][5] = 26
Комментарий: на самом деле было проще получить правильное трехмерное изображение, а затем специализироваться на двумерном случае, чем правильно настроить двумерное дело и затем обобщить на трехмерное дело.
Обратите внимание, что этот метод работает для любого смежного массива (например, статически размещенный пример). Существуют способы динамического размещения массивов, в которых данные не являются смежными, и это не будет работать на таких псевдораборах. Это проблема, если вы выделяете массив указателей, и каждый указатель затем указывает на вектор целых чисел или любую аналогичную схему. К таким «массивам» можно обращаться, используя двойную запись, но сгенерированный код сильно отличается от доступа к истинному многомерному (непрерывному) массиву.
Код в функции A()
не будет обрабатывать «массив», выделенный так (проверка ошибок для краткости опущена), даже если цикл инициализации выглядит почти так же, как цикл инициализации для обычного (непрерывного) 2D-массива :
int **base = malloc(4 * sizeof(*base));
for (int i = 0; i < 4; i++)
base[i] = malloc(6 * sizeof(*base[i]));
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 6; j++)
base[i][j] = 0;
}
for (int i = 0; i < 4; i++)
free(base[i]);
free(base);