复杂的C声明

我只是通过互联网上的一些代码,发现这一点:

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] )()

foo是一个没有参数的函数,它返回一个指向SIZE的SIZE数组的数组的指针…

closures括号到达,再次离开达到一个指针符号:

float * ( *(* foo())[SIZE][SIZE] )()

foo是一个没有参数的函数,它返回一个SIZE指针数组的指针,指向…

左括号再次,所以我们跨过去,再次右转:

float * ( *(* foo())[SIZE][SIZE]) () float * ( *(* foo())[SIZE][SIZE])()

foo是一个没有参数的函数,它返回一个指向SIZE指针数组指针的数组,该指针指向一个没有参数的函数。

并且一直走到最后

float * ( *(* foo())[SIZE][SIZE])()

foo是一个没有参数的函数,它返回一个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(); 

标准规则:find最左边的标识符并按照你的出路,记住[]()*之前绑定:

  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(); 

假设你想把它们存储在一个2×2表中:

 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; } 

请注意,您可以使用几个函数构build不同函数的表格,或者以不同的方式组织相同的函数:

 float *(*(*qwerbl())[SIZE][SIZE])() { static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux}; return tab; } 

这是我能想到做这样的事情的唯一原因。 你不应该经常看到像这样的types(虽然偶尔会出现这种情况,而且我也曾经写过类似的令人讨厌的东西)。

根据cdecl.org

将foo声明为函数返回指向数组SIZE的数组SIZE的指针,以返回指向float的函数

如果你想手工解码,使用Luchian Grigore给出的螺旋规则。

这里要做的最好的事情就是转换成一系列的typedef。

 typedef float * fnReturningPointerToFloat(); typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE]; fnArray* foo(); 

一般来说,你可以尝试cdecl.org,但是你需要replaceSIZE

假设你将SIZE换成12,你会得到:

将foo声明为函数,返回指向数组12的数组12的指针,以返回指向float的函数

我不确定这真的对你有帮助!

这里有两点意见:

  1. 我猜这个代码旁边没有注释,解释它的目的是什么(即不是技术上的解释,而是从function/业务angular度来看它是如何实现的)如果程序员需要使用像这样复杂的东西,它们应该足以向未来的维护者解释它所服务的目的。
  2. 当然,在C ++中,实现同样的事情有更明显,更安全的方法。

这个文件给了我关于如何轻松准备任何C声明的最佳线索:

http://c-faq.com/decl/spiral.anderson.html

有三个简单的步骤:

  • 以未知元素开始,以螺旋/顺时针方向移动; 当生成以下元素时,用相应的英语语句replace它们:

    • [X][] =>数组X的大小…或数组未定义的大小…

    • (type1, type2) =>函数传递type1和type2返回…

    • * =>指向…的指针

  • 继续以螺旋/顺时针方向进行操作,直到所有的令牌都被覆盖。

  • 总是先解决任何括号内的问题!

例如:

  +-------+ | +-+ | | ^ | | 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! 

来自http://cdecl.org/

将foo声明为函数返回指向数组SIZE的数组SIZE的指针,以返回指向float的函数