有人可以解释这是什么意思吗?
int (*data[2])[2];
括号是干什么用的?
在 C 括号中 [] 的优先级高于星号 *
来自维基百科的很好的解释:
要将变量声明为指向数组的指针,我们必须使用括号。这是因为在 C 括号中 ([]) 的优先级高于星号 (*)。因此,如果我们希望声明一个指向数组的指针,我们需要提供括号来覆盖它:
double (*elephant)[20];
这声明了大象是一个指针,它指向的类型是一个包含 20 个双精度值的数组。
要声明指向指针数组的指针,只需组合符号即可。
int *(*crocodile)[15];
来源。
而你的实际情况:
int (*data[2])[5];
data 是一个包含 2 个元素的数组。每个元素都包含一个指向 5 个整数数组的指针。
所以你可以在代码中使用你的“数据”类型:
int (*data[2])[5];
int x1[5];
data[0] = &x1;
data[1] = &x1;
data[2] = &x1;//<--- out of bounds, crash data has no 3rd element
int y1[10];
data[0] = &y1;//<--- compiling error, each element of data must point to an int[5] not an int[10]
有一个非常酷的程序,叫做“cdecl”,你可以下载它用于 Linux/Unix,也可能用于 Windows。您粘贴 C(或 C++,如果您使用 c++decl)变量声明,它会用简单的单词拼写出来。
如果您知道如何阅读C 中的表达式,那么您离阅读复杂的声明只有一步之遥。
做什么
char *p;
真正的意义?这意味着这*p
是一个字符。做什么
int (*data[2])[5];
意思是?这意味着这(*data[x])[y]
是一个 int(提供 0 <= x < 2 和 0 <= y < 5)。现在,想想这意味着什么。data
必须是......一个由 2 个......指针组成的数组......指向 5 个......整数的数组。
你不觉得这很优雅吗?您所做的只是说明表达式的类型。一旦你掌握了这一点,声明就再也不会吓到你了!
“快速规则”是从变量名开始,向右扫描直到你点击a),回到变量名向左扫描直到你点击a(。然后“跳出”这对括号,并重复该过程。
让我们把它应用到一些荒谬的事情上:
void **(*(*weird)[6])(char, int);
weird
是一个指向由 6 个函数组成的数组的指针,每个函数接受一个 char 和一个 int 作为参数,每个函数返回一个指向 void 指针的指针。
既然你知道它是什么以及它是如何完成的......不要这样做。使用 typedef 将您的声明分解为更易于管理的块。例如
typedef void **(*sillyFunction)(char, int);
sillyFunction (*weird)[6];
data[2] - 两个整数的数组
*data[2] - 指向两个整数数组的指针
(*数据[2]) - "
(*data[2])[2] - 一个由 2 个指针组成的数组,指向两个整数数组。
如果你有一个数组:
int myArray[5];
int * myArrayPtr = myArray;
将是完全合理的。myArray
没有方括号的是指向int
. 当您添加括号时,就像您尊重指针一样myArray
。你可以写...
myArrayPtr[1] = 3;
这是完全合理的。使用括号只会使事情更难阅读和理解 IMO。它们表明人们不理解指针、数组和指针算术,这是编译器或链接器从一个到另一个的方式。似乎带括号的你确实得到了边界检查。