Краткий ответ
Данная пользовательская маска объявлена как
int *userMask[3][4];
тогда userMask
имеет тип int*[3][4]
. Это двумерный массив указателей на int. Размер внешнего измерения равен 3, размер внутреннего измерения равен 4. Действительно, это не более чем 3-элементный 1d массив, тип элемента которого является другим 4-элементным 1d массивом, тип элемента которого int*
.
Шаги объяснили
Так что, если вы делаете
userMask[2][maskElement][user]
затем по существу с первыми двумя индексами вы выбираете конкретный указатель из массива 2d:
int * p = userMask[2][maskElement];
затем вы выбираете int где-то смещение от этого указателя, выполняя
p[user]
теперь этот код весь в userMask[2][maskElement][user]
.
Действительный код C
Чтобы сделать это шаг за шагом с действующим кодом c (не беспокойтесь, если вы еще не все поняли в следующем):
int * userMask[3][4] = { { 0 } };
int ** pa = userMask[2]; /* int*[4] becomes int** implicitly */
int * pi = pa[maskElement];
int i = pi[user];
assert(i == userMask[2][maskElement][user]);
Разница между массивами и указателями
Так что я думаю, что покажу вам что-то важное. Вышеуказанный массив не содержит указатели на массивы. Давайте посмотрим, как они ведут себя по-разному, чего многие программисты не ожидают:
int array[5][4][3];
/* int[4][3] implicitly converts to int(*)[3] (pointer to first element) */
int (*parray)[3] = array[0];
int ** pint = (int**) array[0]; /* wrong!! */
Что будет, если мы сделаем parray[1]
и pint[1]
? Первый будет продвигать parray на sizeof(int[3])
байтов (3 * sizeof(int)
), второй будет продвигаться только на sizeof( int* )
байтов. Таким образом, в то время как первый дает вам правильный массив array[0][1]
, второй даст вам ( char * )array[0] + sizeof( int* )
, что мы и не хотим. Но захват неправильного смещения - это еще не все. Поскольку он не знает, к какому массиву обращаются, он попытается интерпретировать то, что в pint[1]
, как int*
. Скажем, ваш массив был инициализирован с 0x00
. Затем он выполнит следующий шаг индексации, основываясь на адресе 0x00 (например, pint[1][0]
). О нет - совершенно неопределенное поведение! Поэтому очень важно подчеркнуть разницу.
* * Заключение тысячи сорок-девять
Это было больше, чем вы просили, но я думаю, что очень важно знать эти детали. Особенно, если вы хотите передать 2d массивы в функции, тогда эти знания действительно полезны.