C 語言多維數組採用行主序:最後一維連續,倒數第二維由最後一維構成,以此類推。
內存地址遞增方向 → a[0][0] a[0][1] a[0][2] a[0][3] | a[1][0] a[1][1] a[1][2] a[1][3] | a[2][0] ...
元素 `a[i][j]` 地址:`base + (i * COLS + j) * sizeof(int)`
`a[i][j][k]` 地址:
offset = (i * 4 * 10 + j * 10 + k) * sizeof(int)
= (i * (D2*D3) + j * D3 + k) * sizeof(int)
維度 `D1, D2, ..., Dn`,索引 `j1, j2, ..., jn`(0 基):
offset = (((j1 * D2 + j2) * D3 + j3) * D4 + ... + jn) * sizeof(element)
// 等價於:
stride[n-1] = 1
stride[k] = stride[k+1] * D_{k+2} (倒推)
offset = Σ (j_k * stride[k])
支援運行時確定維度與大小,封裝創建、訪問、銷毀:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define MAX_DIM 8
typedef struct {
int ndim; // 維數
int *dims; // 各維大小 [ndim]
int *strides; // 步長 [ndim] (以元素為單位)
int *data; // 扁平化數據
size_t total; // 總元素數
} MultiArray;
int marray_init(MultiArray *a, int ndim, ...) {
if (ndim < 1 || ndim > MAX_DIM) return -1;
a->ndim = ndim;
a->dims = malloc(ndim * sizeof(int));
a->strides = malloc(ndim * sizeof(int));
if (!a->dims || !a->strides) return -1;
va_list ap;
va_start(ap, ndim);
a->total = 1;
for (int i = 0; i < ndim; i++) {
int d = va_arg(ap, int);
if (d <= 0) { va_end(ap); return -1; }
a->dims[i] = d;
a->total *= d;
}
va_end(ap);
// 計算步長(行主序)
a->strides[ndim - 1] = 1;
for (int i = ndim - 2; i >= 0; i--)
a->strides[i] = a->strides[i + 1] * a->dims[i + 1];
a->data = calloc(a->total, sizeof(int));
return a->data ? 0 : -1;
}
int marray_set(MultiArray *a, int value, ...) {
va_list ap;
va_start(ap, value);
size_t idx = 0;
for (int i = 0; i < a->ndim; i++) {
int coord = va_arg(ap, int);
if (coord < 0 || coord >= a->dims[i]) { va_end(ap); return -1; }
idx += coord * a->strides[i];
}
va_end(ap);
a->data[idx] = value;
return 0;
}
int marray_get(MultiArray *a, ...) {
va_list ap;
va_start(ap, a);
size_t idx = 0;
for (int i = 0; i < a->ndim; i++) {
int coord = va_arg(ap, int);
if (coord < 0 || coord >= a->dims[i]) { va_end(ap); return -1; }
idx += coord * a->strides[i];
}
va_end(ap);
return a->data[idx];
}
void marray_destroy(MultiArray *a) {
free(a->dims);
free(a->strides);
free(a->data);
a->dims = a->strides = a->data = NULL;
}
// 打印演示(僅 2D)
void marray_print_2d(MultiArray *a) {
if (a->ndim != 2) return;
for (int i = 0; i < a->dims[0]; i++) {
for (int j = 0; j < a->dims[1]; j++)
printf("%4d ", a->data[i * a->strides[0] + j]);
printf("\n");
}
}
int main(void) {
MultiArray a;
marray_init(&a, 2, 4, 6); // 4行6列
int val = 1;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 6; j++)
marray_set(&a, val++, i, j);
marray_print_2d(&a);
// 輸出:
// 1 2 3 4 5 6
// 7 8 9 10 11 12
// 13 14 15 16 17 18
// 19 20 21 22 23 24
printf("a[2][3] = %d\n", marray_get(&a, 2, 3)); // 16
marray_destroy(&a);
return 0;
}
靜態多維數組 `int a[3][4]` 編譯器可展開地址計算為常量;動態容器需間接訪問。熱點路徑建議: