int arr[2][3] =
{
{1, 2, 3},
{1, 2, 3}
}
в памяти выделяется две ячейки, каждая из которых занимает sizeof(int) * 3
и таким образом можно легко обращаться к любому элементу. Например при обращении к последней тройке arr[1][2]
, на уровне указателей это будет выглядеть так *(arr + (sizeof(int) * 3 * 1) + 2)
. Ну и памяти занимает такой массив ровно 2х3.arr[1][2] => *(*(arr + 1) + 2)
и пришел к выводу, что многомерный массив хранится в памяти следующим образом (здесь я буду обозначать память вот так 0[5]
, где 0
- адрес ячейки, [5]
- значение, которое хранится внутри ячейки): 0[адрес 2], 1[адрес 5], 2[1], 3[2], 4[3], 5[1], 6[2], 7[3]
И при таком хранении можно легко понять почему в этой формуле *(*(*(arr + i) + j) + k)
на каждом уровне идет разыменование. Однако при таком способе хранения тот же массив уже занимает 2 + 2x3.int **a;
// или vector<vector<int>> a;
a[10][7];
M*(sizeof(int*))+M*N*sizeof(int)
. Чуть сложнее для vector, но идея такая же.int a[10][3];
a[4][5];
N*M*sizeof(int)
.int[4][5]
к int**
. И такой массив при передаче в функцию надо передавать по типу int[][5]
(можно опустить количество строк. Ибо для адресации нужна лишь длина строк, но нестолбцов, но размер строки указать предется обязательно).arr[1][2] => *(*(arr + 1) + 2)
Это действительно работает, потому что arr имеет тип int[][3]
или int*[3]
. Коспилятор видя arr+1
, знает, что над сместится на 1 размер int[3]
. * разыменовывает это, но при этом указывает на то же место. И получает просто указатель на int начало строки. Фактически тут просто меняется тип указателя с int*[3] на int*. +2 сдвигается в строке на 2 размера int. int arr[6] = { 1,2,3,1,2,3};
*(basePointer + i * LINE_WIDTH + j)
int arr1[2][3];
int (*arr2)[3] = new int[2][3];
int *arr3 = new int[2*3];
int **arr4 = new int*[2];
arr4[0] = new int[3];
arr4[1] = new int[3];
// Следующие утверждения верны:
static_assert(sizeof(arr1) == (sizeof(int)*2*3));
static_assert(sizeof(arr2) == sizeof(int(*)[3]));
static_assert(sizeof(arr3) == sizeof(int*));
static_assert(sizeof(arr4) == sizeof(int**));
static_assert(sizeof(arr1[0]) == (sizeof(int)*3));
static_assert(sizeof(arr2[0]) == (sizeof(int)*3));
static_assert(sizeof(arr3[0]) == sizeof(int));
static_assert(sizeof(arr4[0]) == sizeof(int*));
arr1[i][j]
и это будет работать, но по разному для arr1/2 и arr4.*(arr2 + 1 * 3 + 2);
// или то же самое
arr2[1*3 + 2];