我刚刚在互联网上查看一些代码,发现了这个:
float * (*(*foo())[SIZE][SIZE])()
我该如何阅读这个声明?是否有特定的规则来阅读这样复杂的声明?
我刚刚在互联网上查看一些代码,发现了这个:
float * (*(*foo())[SIZE][SIZE])()
我该如何阅读这个声明?是否有特定的规则来阅读这样复杂的声明?
我有一段时间没有做这个了!
从foo
开始,向右走。
float * (*(*
foo()
)[SIZE][SIZE])()
foo是一个没有参数的函数...
由于有一个闭合括号,所以无法向右走。向左走:
float * (*(
* foo()
)[SIZE][SIZE])()
foo是一个没有参数的函数,返回一个指针
无法再向左走,所以让我们穿过括号,再次向右走
float * (*
(* foo())
[SIZE][SIZE])()
float * (*
(* foo())[SIZE]
[SIZE])()
float * (*
(* foo())[SIZE][SIZE]
)()
Closing parenthesis reached, left again to reach a pointer symbol:foo是一个没有参数的函数,返回一个指向大小为SIZE的数组的SIZE个数组的指针...
float * (
*(* foo())[SIZE][SIZE]
)()
foo是一个不带参数的函数,返回值为指向SIZE个指向SIZE个指向...的指针的数组的指针。float *
( *(* foo())[SIZE][SIZE])
()
、float *
( *(* foo())[SIZE][SIZE])()
foo是一个不带参数的函数,返回值为指向SIZE个指向SIZE个没有参数的函数的指针的数组的指针。float * ( *(* foo())[SIZE][SIZE])()
foo是一个不带参数的函数,返回值为指向SIZE个指向SIZE个不带参数且返回指向float的指针的函数的指针的数组的指针。
无论是谁写的,请教他如何使用typedef
:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();
标准规则:找到最左边的标识符,然后向外扩展,记住[]
和()
在*
之前绑定:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
假设你有一堆返回指向float
的指针的函数:
float *quux();
float *bar();
float *bletch();
float *blurga();
假设您想将它们存储在2x2表中:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab
是一个大小为SIZE x SIZE的指针数组,其中每个指针指向一个返回指向float
类型指针的函数。
现在让我们决定要编写一个函数来返回该表的指针:
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
我认为这是唯一的原因,才会有人这样做。在野外很少见到这种类型(虽然偶尔也会出现,而且我自己也写过类似的东西),所以你不应该看到它们。
根据cdecl.org的说明:
声明foo为一个函数,返回大小为SIZE的指向数组的指针,该数组的每个元素都是指向返回指向浮点数的指针的函数的指针。
如果您想手动解码,请使用Luchian Grigore提供的螺旋规则。
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
SIZE
替换为相应的数字。SIZE
替换为12,则会得到以下结果:现在,使用以下子步骤填写中间部分:
从名称开始,遵循运算符优先级和结合性选择下一个最高优先级运算符,并将对应短语附加到解码字符串的中间部分。
对于剩余声明重复上述子步骤,直到解码过程完成。
注意1:为简单起见,本文忽略了函数参数,但可以在对应()
短语之后包含它们。
注意2:括号(()
)会改变运算符的优先级顺序,就像在任何算术表达式中一样。
注意3:您可以在已解码的声明中使用括号以增加可读性(我在下面的某些示例中已经这样做)。将每组括号视为单个单位。
注意4: n维数组实际上是一个数组(n-1次)的数组。例如 - int A[2][3] - A是包含3个整数的数组的2元素数组,即A是包含2个元素的数组,每个元素都是包含3个整数的数组
例子
int a
- a是int类型的变量float *p
- p是指向float类型的指针char (*p)[3]
- p是指向包含3个字符的数组的指针一些复杂声明的示例
int **p[10]
- p是包含10个指向指针的数组,这些指针指向int类型的变量int (*p)[10]
- p是指向包含10个整数的数组的指针int *p(char *a)
- p是返回指向int类型变量的指针的函数int (*p(char*a))[10]
- p是返回(指向包含10个整数的数组的指针)的函数int *(*p)()
- p是指向(返回指向int类型变量的指针的函数)的指针int (*p()[20])[10]
- p是返回(包含20个(指向包含10个整数的数组的指针)的数组)的函数此规则集也可以与const
一起使用 - const修饰符会修改其左侧的术语(如果存在),否则会修改其右侧的术语。
const int *p[10]
- p 是一个包含 10 个指向 const int 的指针的数组int const *p[10]
- p 是一个包含 10 个指向 const int 的指针的数组(与第 7 个例子相同)int *const p[10]
- p 是一个包含 10 个指向 int 的常量指针的数组现在是一个非常复杂的例子,实际上在实践中不会使用,但仍然可以用来演示解码过程。
char *(*(**foo[][8])())[]
- foo 是一个包含 (包含 8 个指向 (指向 (返回指向 (包含指向 char 的指针的数组) 的函数的指针))) 的数组的数组现在最后一步是对问题中给出的声明进行解码。
float * (*(*foo())[SIZE][SIZE])()
- foo 是一个返回 (指向大小为 SIZE 的数组的指针,其中每个元素都是大小为 SIZE 的数组的指针,这些指针又指向一个返回指向 float 的指针的函数) 的函数的指针。
以下是我阅读此解码过程的文章链接
例 10 取自本文
这篇文章给了我关于如何轻松地阅读任何C语言声明的最好线索:
http://c-faq.com/decl/spiral.anderson.html
有三个简单的步骤需要遵循:
从未知元素开始,以螺旋式/顺时针方向移动;当遇到以下元素时,将其替换为相应的英文语句:
[X]
或[]
=> 数组X大小为...或数组未定义大小...
(type1, type2)
=> 函数传递类型1和类型2,返回...
*
=> 指向...一直以这种螺旋式/顺时针的方式进行,直到所有标记都被覆盖。
始终首先解析括号中的内容!
例如:
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!
float * (*(*foo())[SIZE][SIZE])()
上的 cdecl.org,其中SIZE
是 16。 - Alvin Wongint a[5][6]
,因为不遵循优先顺序。 - kotlomoy