2013-02-27 74 views
68

我只是通过一些代码会在互联网上,发现这个:复杂的C声明

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

如何阅读此声明?阅读这种复杂声明是否有一套特定的规则?

+21

[螺旋规则](http://c-faq.com/decl/spiral。anderson.html) – 2013-02-27 11:58:18

+16

http://cdecl.org/ – juanchopanza 2013-02-27 11:59:59

+0

使用http://cdecl.org/ – 999k 2013-02-27 12:00:06

回答

117

我还没有在一段时间做到了这一点!

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数组的数组的函数...

闭括号达到,再次离开以达到指针符号:

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

foo是不带任何参数返回一个指向大小为指针的大小数组的数组的功能...再次

左括号,所以我们超越了这去便又:

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

foo是不带参数返回一个指针到SIZE指针SIZE数组的数组,以不带参数的功能的功能...

并留给端

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

foo是不带任何参数返回一个指向大小为指针的大小数组的数组不带参数的返回指针的函数等漂浮


和谁写的,请教他用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(); 
+57

+1代表“谁写了这些,p租赁教他使用typedef“ – 2013-02-27 14:31:36

+2

请注意,”无参数“部分仅适用于C++;对于C来说,它意味着“未指定的参数列表”(但它不能是可变参数列表,因为它们必须具有完整的原型范围,即使在C中也是如此)。 – 2013-03-06 01:08:08

3

一般情况下,你可以尝试cdecl.org但你需要替换SIZE

说你换SIZE 12,你会得到:

声明富作为函数返回指针数组12 指针函数返回指向浮点数的函数

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

两个结论:这里:

  1. 我猜测,这个代码没有它解释什么它的目的是(旁边有一个评论即不知道是什么它就是什么,但在技术说明从功能/业务角度实现)如果程序员需要使用像这样复杂的东西,他们应该足以向未来的维护者解释其服务目的。
  2. 当然,在C++中,实现同样的事情有更明显的和更安全的方法。
+3

这是由于“SIZE”的原因,你必须使用literal来代替它(你自己用常量代替它) 。 – 2013-02-27 12:02:32

+0

用一些数字代替SIZE !! – Kaunteya 2013-02-27 12:04:46

+0

回答更改 - 感谢您的反馈。 – 2013-02-27 12:09:42

6

根据cdecl.org

声明FOO作为函数返回指针到指针的数组大小 的阵列大小的功能返回指针到浮动

使用由Luchian格里戈雷给出的螺旋的规则如果你想手工解码。

1

http://cdecl.org/

声明富作为函数返回指针,指针数组大小的数组大小,以函数返回指针浮

4

这里要做的最好的事情是转换为一系列typedefs。

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

这花了我一分钟。 – QuentinUK 2013-02-27 12:24:18

97

标准规则:找到最左边的标识和工作的方式了,记住,[]()绑定之前*

  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是指向返回指向float的指针的函数指针的SIZE x SIZE数组。

现在让我们来决定我们想要一个函数返回一个指向该表:

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

这是我能想到做这种事情的唯一原因。你不应该经常在野外看到这种类型的东西(尽管偶尔会出现这种情况,而且我曾经写过类似的令人发指的东西)。

+1

qwerbl?您几乎用完了泛型变量名称,是不是:-) +1的基本原理。我确定“深度相关”类型经常出现,但通常也会涉及到结构或类,这就使得命名问题自然消失 - 就像引入某种类型定义时的情况一样。 – Kos 2013-02-27 12:39:33

+0

@Kos:是的。还没有我的咖啡因的RDA,不能拿出更好的东西。 – 2013-02-27 14:11:12

+1

维基百科有一个[metasyntactic变量列表](http://en.wikipedia.org/wiki/Metasyntactic_variable#English),这样你就不会跑出来:富,酒吧,巴兹,qux,QUUX,corge,grault,garply ,waldo,fred,plugh,xyzzy,thud。 – 2013-02-27 17:08:17

2

本文gaves我关于最好的线索,如何轻松地准备任何C声明:

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

有三个简单的步骤如下:

  • 与未知的开始元素,以螺旋/顺时针方向移动; ecountering以下元素时与相应的英文语句代替它:

    • [X]或...或数组的大小未定义= []>阵列X大小...

    • (type1, type2) =>功能通过type1和类型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!