C 語言原生多維陣列需在編譯期決定維度,且難以作為函數參數傳遞。本文實作一個通用的動態多維陣列抽象資料型別 (ADT),支援任意維度(最多 8 維)、執行期指定維界、元素存取與列印,核心在於**行優先**位址計算公式的預計算與泛型操作介面。
對維度為 dim、各維大小 bounds[0..dim-1] 的陣列,索引 (i0,i1,...,i_{dim-1}) 的線性位移:
offset = i0*B0 + i1*B1 + ... + i_{dim-2}*B_{dim-2} + i_{dim-1}
其中 Bk = bounds[k+1] * bounds[k+2] * ... * bounds[dim-1] (基數乘積)
B_{dim-1} = 1
預先計算 base_add[k] = Bk,存取時只需 offset = Σ index[k] * base_add[k],O(dim) 時間。
typedef struct {
int dim; // 維度
int *bounds; // 各維大小 [dim]
int *base_add; // 基數乘積 [dim]
int *data; // 線性儲存空間
} Array;
array_init(Array *a, int dim, ...):可變參數指定各維大小,配置記憶體並預計算 base_add。array_set_value(Array *a, int val, ...) / array_get_value:可變參數指定索引,邊界檢查後存取。array_print_line(Array *a):按行優先順序格式化列印。array_destroy(Array *a):釋放三個動態陣列。int array_init(Array *a, int dim, ...) {
if (dim < 1 || dim > 8) return -1;
a->dim = dim;
a->bounds = malloc(dim * sizeof(int));
a->base_add = malloc(dim * sizeof(int));
va_list ap; va_start(ap, dim);
long total = 1;
for (int i = 0; i < dim; i++) {
a->bounds[i] = va_arg(ap, int);
total *= a->bounds[i];
}
va_end(ap);
a->data = malloc(total * sizeof(int));
a->base_add[dim-1] = 1;
for (int i = dim-2; i >= 0; i--)
a->base_add[i] = a->base_add[i+1] * a->bounds[i+1];
return 0;
}
int array_get_locate(Array *a, va_list ap) {
int offset = 0;
for (int i = 0; i < a->dim; i++) {
int idx = va_arg(ap, int);
if (idx < 0 || idx >= a->bounds[i]) return -1;
offset += idx * a->base_add[i];
}
return offset;
}
Array a;
array_init(&a, 2, 4, 6);
for (int i = 0; i < 4; i++)
for (int j = 0; j < 6; j++)
array_set_value(&a, i*6+j+1, i, j);
array_print_line(&a); // 依記憶體順序列印
// 以矩陣形式列印
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 6; j++)
printf("%-7d", array_get_value(&a, i, j));
puts("");
}
array_destroy(&a);
void *data + size_t elem_size,操作函數傳入 memcpy。for_each 模式。此實作展示 C 語言以結構體封裝資料與操作、可變參數處理多維索引、預計算優化存取效能的經典模式,可作為科學計算庫、影像處理框架的基礎組件。