Гм-хм, вы слишком переоцениваете "откровение" из детского мультика: "Как вы яхту назовете ...". > Как научишься создавать многомерный массив на куче, а не на стеке, приходи поговорим
Предпочту подождать с разговором, пока анонимный "Уважаемый", "Знаток", "Эксперт" (эпитет "Скромный" не упомянут видимо из скромности) не подучит матчасть 🙄
cat arr3.c && gcc -O2 arr3.c && ./a.out 2 2 1 1337
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define DIM 3
#define TYPE int
const size_t ARR_LEN = DIM * DIM * DIM ;
const size_t ARR_SIZE = ARR_LEN * sizeof(TYPE);
typedef TYPE array[DIM][DIM][DIM];
void foo(array bar, int x, int y, int z, char val) {
bar[x][y][z] = val;
}
int main(int argc, char** argv) {
array *arr = malloc(ARR_SIZE);
for (size_t i = 0; i < ARR_LEN; i++) {
*((TYPE*)arr + i) = atoi(argv[4]) + i;
printf ("%p:%lu = %lu\n",((TYPE*)arr + i), i, atoi(argv[4]) + i);
}
foo(*arr, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]) + 1);
for (size_t x = 0; x < DIM; x++)
for(size_t y = 0; y < DIM; y++)
for(size_t z = 0; z < DIM; z++)
printf("[%lu][%lu][%lu]: %d\n", x,y,z, (*arr)[x][y][z]);
return 0;
}
0x800a45000:0 = 1337
0x800a45004:1 = 1338
0x800a45008:2 = 1339
0x800a4500c:3 = 1340
...
0x800a45060:24 = 1361
0x800a45064:25 = 1362
0x800a45068:26 = 1363
[0][0][0]: 1337
[0][0][1]: 1338
[0][0][2]: 1339
..
[2][1][2]: 1360
[2][2][0]: 1361
[2][2][1]: 58
[2][2][2]: 1363
foo:
.LFB1:
.cfi_startproc
# arr3.c:12: void foo(array bar, int x, int y, int z, char val) {
mov eax, DWORD PTR [esp+8] # x, x
# arr3.c:13: bar[x][y][z] = val;
mov ecx, DWORD PTR [esp+4] #, bar
mov edx, DWORD PTR [esp+12] # y, y
lea eax, [eax+eax*8] # tmp95,
lea eax, [ecx+eax*4] # tmp97,
movsx ecx, BYTE PTR [esp+20] # val, val
lea edx, [edx+edx*2] # tmp100,
add edx, DWORD PTR [esp+16] # tmp101, z
mov DWORD PTR [eax+edx*4], ecx # *_3, val
# arr3.c:14: }
ret
.cfi_endproc
(это все помимо того, что абсолютно никто не мешает обернуть обращение к одномерному массиву в макрос и не париться - но … раз анонимы в книжке^W на стековерфлоу прочитали "нужно использовать массив указателей на указателей, иначе никак!", то так и будут, не задумываясь, их использовать 🙄)
И, чтобы начать немного соответствовать никам, не забудьте завернуть доказательства, что последовательная загрузка из _таблицы указателей_ :
void foo2(int*** bar, int x, int y, int z, char val) {
bar[x][y][z]
}foo2:
.LFB1:
.cfi_startproc
# arr3.c:14: bar[x][y][z] = val;
movsx rsi, esi # x, tmp107
movsx rdx, edx # y, tmp108
movsx rcx, ecx # z, tmp109
movsx r8d, r8b # val, tmp110
mov rax, QWORD PTR [rdi+rsi*8] # *_3, *_3
mov rax, QWORD PTR [rax+rdx*8] # *_7, *_7
mov DWORD PTR [rax+rcx*4], r8d # *_11, val
# arr3.c:16: }
ret
.cfi_endproc
будет быстрее вычисления адреса (особенно при размерах, кратных 2-м).
foo:
.LFB1:
.cfi_startproc
# arr3.c:13: bar[x][y][z] = val;
movsx rsi, esi # x, tmp101
movsx rdx, edx # y, tmp102
movsx rcx, ecx # z, tmp103
movsx r8d, r8b # val, tmp104
sal rsi, 10 # tmp93,
sal rdx, 4 # tmp97,
add rsi, rdi # tmp94, tmp100
add rdx, rcx # tmp98, z
mov DWORD PTR [rsi+rdx*4], r8d # *_3, val
# arr3.c:14: }
ret
.cfi_endproc