简短的回答
给定 userMask 被声明为
int *userMask[3][4];
然后userMask
有类型int*[3][4]
。这是一个指向 int 的二维指针数组。外部维度的大小为 3,内部维度的大小为 4。实际上无非就是一个 3 元素一维数组,其元素类型是另一个 4 元素一维数组,其元素类型为int*
。
步骤说明
所以如果你这样做
userMask[2][maskElement][user]
然后基本上使用前两个索引从二维数组中选择特定指针:
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]);
数组和指针的区别
所以我想我向你展示了一些重要的东西。上面的数组不包含指向数组的指针。让我们看看它们的行为有多么不同,这是许多 c 程序员没有想到的:
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]
and会发生什么pint[1]
?第一个将按sizeof(int[3])
字节(3 * sizeof(int)
)推进数组,第二个将仅按sizeof( int* )
字节推进。所以实际上,虽然第一个给你正确的数组array[0][1]
,第二个会给你( char * )array[0] + sizeof( int* )
,这是我们真的不希望它出现的地方。但是抓住错误的偏移量并不是全部。因为它不知道访问了一个数组,所以它会尝试将 at 解释pint[1]
为int*
. 假设您的数组已使用0x00
. 然后它将根据地址 0x00 执行下一个索引步骤(pint[1][0]
例如)。哦不 - 完全未定义的行为!因此,强调差异非常重要。
结论
这超出了您的要求,但我认为了解这些细节非常重要。特别是如果您想将二维数组传递给函数,那么这些知识非常有用。