有人能解释一下这是什么意思吗?
int (*data[2])[2];
括号有什么作用?
在C语言中,方括号[]比星号*的优先级高。
以下是维基百科上的好解释:
为了将一个变量声明为数组指针,我们必须使用括号。这是因为在C语言中,方括号([])比星号(*)的优先级更高。因此,如果我们想声明一个指向数组的指针,我们需要提供括号来覆盖这一点:
double (*elephant)[20];
这声明了elephant是一个指针,它所指向的类型是一个包含20个双精度浮点数的数组。int *(*crocodile)[15];
来源.
而你的实际情况:
int (*data[2])[5];
数据是一个由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++decl,则是C++)变量声明,程序会用简单的语言把它解释出来。
这是什么意思?
char *p;
*p
是一个字符。这句话的含义是什么?int (*data[2])[5];
(*data[x])[y]
是一个int类型(假设0 <= x < 2且0 <= y < 5)。现在,想一想这意味着什么。 data
必须是...一个包含2个指向数组的指针...的数组,每个数组包含5个整数。
你不觉得这很优雅吗?你只是在声明表达式的类型。一旦你掌握了这一点,声明就再也不会让你感到害怕了!
"快速规则"是从变量名开始,向右扫描直到遇到),返回到变量名,向左扫描直到遇到(。然后“跳出”括号对,并重复这个过程。
让我们将其应用于一些荒谬的事情:
void **(*(*weird)[6])(char, int);
weird
是一个指向包含6个指向函数的指针数组的指针,每个函数都接受一个char和一个int作为参数,并返回一个指向指向void的指针的指针。
既然你知道它是什么以及如何完成... 不要这样做。使用typedef将声明拆分成更易处理的块。例如:
typedef void **(*sillyFunction)(char, int);
sillyFunction (*weird)[6];
using
将名称映射到类型。 - IS4int myArray[5];
int * myArrayPtr = myArray;
这是完全合理的。没有方括号的myArray
是一个指向int
的指针。当你添加方括号时,就像你解引用了指针myArray
。你可以这样写...
myArrayPtr[1] = 3;
这是非常合理的。在我看来,使用括号只会让事情变得更难读懂和理解。而且它们表明人们不理解指针、数组和指针算术运算,而编译器或链接器正是通过这些来进行转换。不过使用括号似乎可以进行边界检查。
data[2] - 一个包含两个整数的数组
*data[2] - 指向一个包含两个整数的数组的指针
(*data[2]) -
(*data[2])[2] - 包含两个指向包含两个整数的数组的指针的数组。