25

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

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

这具体指的是什么?它是一个矩阵,其中每个元素都是一个指针吗?还是它指向一个大小为 [3][4] 的矩阵?

谢谢


我想我的问题是userMask[2][maskElement][user]当它被声明为int. userMask 不是必须让它int[]正常工作吗?我一定没有理解这个权利...

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

4

9 回答 9

42

简短的回答

给定 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]例如)。哦不 - 完全未定义的行为!因此,强调差异非常重要。

结论

这超出了您的要求,但我认为了解这些细节非常重要。特别是如果您想将二维数组传递给函数,那么这些知识非常有用。

于 2008-11-08T17:02:19.380 回答
18

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

在您的后续行动中,您表明该数组的使用方式如下:

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

在这种情况下,每个元素userMask实际上都应该指向一个ints 数组。(Anint*可以指向单个int或一个 s 数组int)。要确定这一点,请检查将值分配给 的代码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.
于 2008-11-08T16:07:33.280 回答
11
int *userMask[3][4] = {0};

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

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

将是指向二维整数数组的指针。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]
于 2008-11-08T16:14:56.823 回答
3
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] 处向量的第用户元素非零

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

然后设置结果 = true。

于 2008-11-08T17:45:15.610 回答
2

应用由内而外的规则。

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

从声明的内柱部分开始,

userMask

是名字

userMask[3] 

为其中 3 个分配空间(是其中的一个向量)

userMask[3][4] 

userMask[3]为 4分配空间

int *

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

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

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

是一个 3x4 的 int * 数组,初始化为 0。

于 2008-11-08T17:34:39.907 回答
0

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

于 2008-11-08T16:23:24.573 回答
0

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.

于 2008-11-08T16:27:06.033 回答
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];

这需要 i 指向一个区域,其中几个 int 相互排列,当然,就像一个数组。

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

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

选择存储在 [2][maskElement] 中的用户掩码指针,并为用户用户评估它

于 2008-11-08T17:02:27.710 回答
-1

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

如果它指向大小为 [3][4] 的矩阵,则代码将是

int userMask[3][4]={0};
于 2008-11-08T16:09:10.907 回答