复杂的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的函数
我不确定这真的对你有帮助!
这里有两点意见:
- 我猜这个代码旁边没有注释,解释它的目的是什么(即不是技术上的解释,而是从function/业务angular度来看它是如何实现的)如果程序员需要使用像这样复杂的东西,它们应该足以向未来的维护者解释它所服务的目的。
- 当然,在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!
将foo声明为函数返回指向数组SIZE的数组SIZE的指针,以返回指向float的函数