什么是`int * userMask `指向?

我正在修改一些代码并遇到一个声明,我无法理解:

int *userMask[3][4] = {0}; 

究竟是什么指向? 它是一个矩阵,每个元素都是指针吗? 或者它指向一个大小的矩阵[3] [4]?

谢谢


我想我的问题是userMask[2][maskElement][user]在声明为int时如何工作。 userMask不能为int[]以使其正常工作吗? 我不能理解这个权利……

请注意,感谢您对cdecl Robert的建议。 但是,有没有人知道如何在XP命令提示符中使用它? 我能得到的只是语法错误:(

简短的回答

给定userMask声明为

 int *userMask[3][4]; 

那么userMask类型为int*[3][4] 。 它是一个指向int的2d数组。 外部维度的大小为3,内部维度的大小为4.实际上,这只不过是一个3元素的1d数组,其中元素类型是另一个4元素1d数组,其元素类型是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]); 

数组和指针之间的区别

所以我想我告诉你一些重要的事情。 上面的数组包含指向数组的指针。 让我们看看它们的行为有多么不同,这是许多程序员不期望的:

 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]会发生什么? 第一个将通过sizeof(int[3])字节( 3 * sizeof(int) )推进parray,第二个将仅通过sizeof( int* )字节前进。 所以实际上第一个给你正确的数组array[0][1] ,第二个会给你( char * )array[0] + sizeof( int* ) ,这是我们真的不希望它的某个地方。 但抓住错误的偏移并不是全部。 因为它不知道访问了数组,所以它将尝试将pint[1]中的内容解释为int* 。 假设您的数组已使用0x00初始化。 然后它将根据地址0x00(例如,执行pint[1][0] )执行下一个索引步骤。 哦不 – 完全未定义的行为! 因此强调差异非常重要。

结论

这比你要求的要多,但我认为了解这些细节非常重要。 特别是如果你想将2d数组传递给函数,那么这些知识非常有用。

这是一个二维数组,其中每个元素都是一个指向int的指针,所有指针都初始化为零。

在您的后续操作中,您将显示数组的使用方式如下:

 if(userMask[2][maskElement][user] && blah) result = true; 

在这种情况下, userMask每个元素实际上应该指向一个int数组。 ( int*可以指向单个intint的数组)。 要确定这一点,请检查为userMask分配值的代码。 例如,可以写:

 int userArray[2] = { 10, 20 }; userMask[0][0] = userArray; // userMask[0][0] points to the // first element of userArray. 

然后以下代码索引到userArray

 int value = userMask[0][0][1]; // sets value = userArray[1], giving 20. 
 int *userMask[3][4] = {0}; 

是一个二维数组,其中每个成员都是一个指向int的指针。 此外,所有成员都初始化为空指针。

 int (*userMask)[3][4]; 

将是一个指向二维int数组的指针。 C中的括号比*更紧密,因此需要括号来创建指向数组的指针。

cdecl是一个简单的实用程序,您可以下载它来解释复杂的声明:

 cdecl> explain int *userMask[3][4] declare userMask as array 3 of array 4 of pointer to int 

它也可以做相反的事情:

 cdecl> declare userMask as pointer to array 3 of array 4 of int int (*userMask)[3][4] 
 if(userMask[2][maskElement][user] && blah) result = true; 

这里的第二部分是C中没有数组; 只有指针算术。 根据定义, p[i]总是等于*(p+i)所以

 userMask[2][maskElement][user] 

相当于

 *((userMask[2][maskElement])+user) 

代码在某个地方分配一个向量(我把钱从malloc(3c)或类似的调用中下注)到该数组中的指针; 现在你的如果说

如果 userMask [2] [maskElement]处的向量的用户元素不为零

然后,如果 blah为非零(由于&&的短路评估,如果第一个合取为0,则不会评估第二个合取)

然后设置result = true。

应用由内而外的规则。

 int *userMask[3][4] = {0}; 

从宣言的内部部分开始,

 userMask 

是名字

 userMask[3] 

为它们中的3个(向量)分配空间

 userMask[3][4] 

为4 userMask[3]分配空间

 int * 

告诉我们userMask项是int类型指针

然后= {0}是一个初始化器,其中所有元素都是0 。 所以

 int *userMask[3][4] = {0}; 

是int *的3×4数组,初始化为0。

我认为该语句访问usermask数组的第三行,然后访问该行中的maskElement’th指针,因为这是一个int指针,它可以指向一个int数组的开头(想想字符串),我假设它正在进行,并且该数组由用户进行子索引。

userMask[2]的类型为int*[]
userMask[2][maskElement]的类型为int*
userMask[2][maskElement][user]的类型为int

声明

 int *userMask[3][4] = {0}; 

是简写

 int *userMask[3][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; 

其中每个零都隐式转换为(int*)0

如果您这样阅读它会有所帮助:

 type variablename[array_spec]; 

在这种情况下:int * usermask [3] [4];

所以它是一个int *的矩阵。

现在,由于c不区分指针和数组,因此可以对指针使用数组索引。

 int* i; int the_int_behind_i = *(i+1); int also_the_int_behind_i = i[1]; 

这需要我指向一个区域,在这个区域中,几个整体排列在一起,当然,就像arrays一样。

请注意,最后一个示例中使用的索引operator []看起来像第一个中的array_spec,但两者完全不同。

所以:userMask [2] [maskElement] [user]

选择存储在[2] [maskElement]中的usermask指针,并为用户用户进行评估

它是一个矩阵,每个元素都是一个指针。

如果它指向一个大小为[3] [4]的矩阵,代码本来就是

 int userMask[3][4]={0};