C++ int(*a)[3]的解释
在C语言中使用数组和指针时,人们很快就会发现它们根本不是等价的,尽管乍一看似乎是这样。我知道L值和R值的区别。尽管如此,最近我试图找出我可以与二维数组结合使用的指针类型,即C++ int(*a)[3]的解释,c++,c,arrays,pointers,types,C++,C,Arrays,Pointers,Types,在C语言中使用数组和指针时,人们很快就会发现它们根本不是等价的,尽管乍一看似乎是这样。我知道L值和R值的区别。尽管如此,最近我试图找出我可以与二维数组结合使用的指针类型,即 int foo[2][3]; int (*a)[3] = foo; 然而,尽管有*和[]的常规运算符优先级规则,我还是无法找出编译器是如何“理解”a的类型定义的。如果改用typedef,问题会变得简单得多: int foo[2][3]; typedef int my_t[3]; my_t *a = foo; 最后,有人能
int foo[2][3];
int (*a)[3] = foo;
然而,尽管有*
和[]
的常规运算符优先级规则,我还是无法找出编译器是如何“理解”a的类型定义的。如果改用typedef,问题会变得简单得多:
int foo[2][3];
typedef int my_t[3];
my_t *a = foo;
最后,有人能回答我关于编译器如何读取术语int(*a)[3]
的问题吗inta[3]
很简单,int*a[3]
也很简单。但是,为什么它不是int*(a[3])
编辑:当然,我不是说“typecast”,而是说“typedef”(这只是一个打字错误)。为什么“notint*(a[3])
”是正确的(指你的最后一个问题)?int*(a[3])
与普通的int*a[3]
相同。大括号是多余的。这是一个指向int
的3个指针数组,你说你知道它的意思
int(*a)[3]
是指向3个int
数组的指针(即指向int[3]
类型的指针)。在这种情况下,大括号很重要。您自己提供了一个正确的示例,该示例通过中间typedef
进行等效声明
简单流行的由内而外的C声明读取规则在这种情况下非常有效。在int*a[3]
声明中,我们必须先从a
开始,然后向右走,即得到a[3]
,这意味着a
是一个由3个某物组成的数组(依此类推)。int(*a)[3]
中的()
改变了这一点,因此我们不能直接从*a
开始:a
是指向某个东西的指针。继续解码该声明,我们将得出结论,某物是一个3int
的数组
在任何情况下,都可以找到一本关于阅读C声明的好教程,其中有很多可以在网上找到。编译器可能比您更容易解释。一种语言定义了一组规则来定义有效表达式的组成部分,编译器使用这些规则来解释这些表达式(听起来可能很复杂,但编译器已经被详细研究过了,并且有很多标准化的算法和工具可用,您可能想了解一下)。是一个将C表达式翻译成英语的工具。源代码可以在网站上找到,因此您可以查看它。C++编程语言的书包含了编写程序的样例代码,如果我没有错的话。 至于你自己解释这些表达,我发现C++中的第1卷:中的思考技巧是最好的。 要定义指向没有参数和返回值的函数的指针,可以说: 无效(*funcPtr)() 当你看到一个复杂的 像这样的定义,最好的方法 进攻是从中间开始 找到你的出路。“从 “中间”的意思是从中间开始 变量名,即funcPtr。 “走出困境”意味着看 向右移动到最近的项目 (本案中无任何规定;权利 括号使你停下来),然后 向左看(指针表示为 按星号),然后查看 右(空参数列表) 表示一个不接受任何条件的函数 参数),然后向左看 (void,表示函数 没有返回值)。这 右-左-右运动与 大多数声明 复习“从中间开始” (“funcPtr是一个…”),向右走 (那里什么都没有——你被警察拦住了 右括号),转到左边 查找“*”(“…指向…”的指针), 向右走,找到空的 参数列表(“…函数 不接受任何参数…),请转到 左键并找到空白(“funcPtr是一个 指向不接受任何值的函数的指针 参数并返回void”) 你可以在上免费下载这本书。让我们尝试将其应用于
int(*a)[3]
:
您可能会发现这篇文章很有帮助:
T
的指针可以指向类型T
的对象:
int *pi;
int i;
pi = &i;
以上内容很容易理解。现在,让我们把它变得更复杂一点。您似乎知道数组和指针之间的区别(即,您知道数组不是指针,但有时它们的行为与指针类似)。因此,您应该能够理解:
int a[3];
int *pa = a;
但为了完整性起见:在赋值中,名称a
相当于&a[0]
,即指向数组a
的第一个元素的指针。如果您不确定这是如何工作的以及为什么工作的,那么有许多答案确切地解释了数组名称何时“衰减”到指针以及何时不衰减:
- 我对题为
- 当数组的名称不衰减为指针时的另一个实例,以及
- T
int foo[2][3];
/* declare p somehow */ p = foo[0];
/* What should be the type of q? */ q = foo;
q = &foo[0];
int (*q)[3];
$ cdecl cdecl> declare p as pointer to array 3 of int int (*p)[3] cdecl> explain int (*p)[3] declare p as pointer to array 3 of int
int (*a)[3]; a # "a is" (* ) # parentheses, so precedence changes. # "a pointer to" [3] # "an array [3] of" int ; # "int".
int *a[3]; a # "a is" [3] # "an array [3] of" * # can't go right, so go left. # "pointer to" int ; # "int".
char *(*(*a[])())() a # "a is" [] # "an array of" * # "pointer to" ( )() # "function taking unspecified number of parameters" (* ) # "and returning a pointer to" () # "function" char * # "returning pointer to char"
int* a[3];
typedef int threeInts[3]; threeInts* pointerToThreeInts;
[/tmp]$ cdecl Type `help' or `?' for help cdecl> explain int (*a)[10]; declare a as pointer to array 10 of int