70

インターネットでいくつかのコードを調べていたところ、次のことがわかりました。

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

この宣言の読み方は?このような複雑な宣言を読み取るための特定のルール セットはありますか?

4

8 に答える 8

119

私はしばらくこれをしていません!

から始めて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 は、 ... への SIZE ポインターの SIZE 配列の配列へのポインターを返す、引数のない関数です。

再び左括弧なので、それをまたいで右に進みます。

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

foo は、引数のない関数への SIZE ポインターの SIZE 配列の配列へのポインターを返す引数のない関数です...

そして最後まで残した

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

foo は SIZE 配列の配列へのポインタを返す引数のない関数です float へのポインタを返す引数のない関数への SIZE ポインタ


そして、それを書いた人は誰でも、彼に使い方を教えてください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();
于 2013-02-27T12:20:31.630 に答える
100

標準的なルール:左端の識別子を見つけて、それを覚えて前[]()バインドして*ください。

            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にポインタを返す関数へのポインタのSIZExSIZE配列です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;
}

これが私がこのようなことをすることを考えることができる唯一の理由です。このようなタイプは、野生ではあまり見られないはずです(ただし、ときどき発生し、同様に凶悪なものを書いたことで罪を犯しました)。

于 2013-02-27T12:31:15.390 に答える
6

cdecl.orgによると

foo を配列へのポインタを返す関数として宣言する 配列の SIZE 関数へのポインタの SIZE float へのポインタを返す

手で解読したい場合は、Lukian Grigore によって与えられたスパイラル ルールを使用します。

于 2013-02-27T12:01:32.383 に答える
4

ここで行う最善の方法は、一連の typedef に変換することです。

typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
于 2013-02-27T12:21:42.977 に答える
3

通常、cdecl.orgを試すことができますが、代わりにSIZE

12を交換SIZEすると、次のようになります。

float へのポインターを返す関数へのポインターの配列 12 の配列 12 へのポインターを返す関数として foo を宣言する

それが本当にあなたを助けるかどうかはわかりません!

ここでの2つの観察:

  1. このコードには、その目的を説明するコメントが横になかったと思います(つまり、それが何であるかの技術的な説明ではなく、機能/ビジネスの観点から何を達成しているのか)これと同じくらい複雑なものですが、将来のメンテナーにそれがどのような目的を果たすかを説明するのに十分なはずです.
  2. 確かに C++ では、同じことを達成するためのより明白で、おそらくより安全な方法があります。
于 2013-02-27T12:01:22.180 に答える
2

このドキュメントは、C 宣言を簡単に準備する方法についての最良の手がかりを与えてくれました。

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

次の 3 つの簡単な手順に従います。

  • 未知の要素から始めて、らせん/時計回りの方向に移動します。次の要素に遭遇した場合、それらを対応する英語のステートメントに置き換えます。

    • [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!
于 2013-03-05T19:59:13.743 に答える
1

http://cdecl.org/から

foo を配列へのポインタを返す関数として宣言する 配列の SIZE 関数へのポインタの SIZE float へのポインタを返す

于 2013-02-27T12:01:55.467 に答える