17

私はいくつかのC宣言を理解しようとしています。これらの C 宣言の意味は何ですか?

double (*b)[n];
double (*c[n])();
double (*d())[n];
4

4 に答える 4

13
double (*b)[n];

b は、n 個の double の配列へのポインターです。

double (*c[n])();

c は、指定されていない数の引数を取り、double を返す関数への n 個のポインターの配列です。

double (*d())[n];

d は、指定されていない数の引数を取り、n 個の double の配列へのポインターを返す関数です。

一般に、この種の宣言を頭の中で解析するには、次のアプローチを取ります。たとえば、最後の宣言を見てみましょう

 double (*d())[n];

d に対して最初に行われることは何ですか? () で呼び出されるので、不特定多数の引数を取って returnig を返す関数です。結果はどうなりますか? 逆参照 (*) されているため、 へのポインターです。次に、結果にインデックスが付けられるため、n の配列になります。何が残るでしょうか。double、したがってdoublesの。太字の部分を読むと、答えが得られます。

別の例を見てみましょう

 void (*(*f)(int)[n])(char)

ここでは、f が最初に逆参照されるため、これは...へのポインターであり、次に (int) で呼び出されます。したがって、関数は int を取り、 を返します。結果は [n] でインデックス付けされるため、 n の配列になります。結果は再び逆参照されるため . 次に、結果は (char) によって呼び出されるため、関数は char を受け取り、(残っているものはすべて void) voidを返します。したがって、 f はint を取り、 char を取り void を返す関数への n 個のポインタの配列を返す関数へのポインタです。

HTH

于 2012-11-06T08:55:06.950 に答える
9

C 宣言を解析するための基本的なルールは、「右から左に読み取り、括弧のペアを離れるときは裏返しに右にジャンプする」です。つまり、最も深くネストされた括弧のペアを開始し、右に向かって自分自身を調べます。技術的には、演算子の結合性を知っている必要がありますが、ほとんどの状況では十分に機能します。

この(簡略化された)ルールを質問に適用しましょう:


double (*b)[n];
         ^

b は

double (*b)[n];
        ^

へのポインタ

double (*b)[n];
           ^^^

と配列

double (*b)[n];
^^^^^^

ダブルスの。


double (*c[n])();
         ^^^^

cはの配列です

double (*c[n])();
        ^

へのポインタ

double (*c[n])();
              ^^

機能

double (*c[n])();
^^^^^^

倍返し。


double (*d())[n];
         ^^^

d は関数です

double (*d())[n];
        ^

へのポインタを返す

double (*d())[n];
             ^^^

の配列

double (*d())[n];
^^^^^^

ダブルス


ほとんどの *nix には、C 宣言文字列を取り、それを自然言語文に変換するcdeclと呼ばれる便利なユーティリティがあります。

于 2012-11-06T09:04:05.643 に答える
4

この方法で試してみましょう。

まず、次の 3 つの記号に慣れておく必要があります。

1. * -- ポインター。
2. [] -- 配列。
3. () -- 関数。(注意: 括弧ではありません)

例として「double (*d())[n]」を取り上げます。

最初のステップは、宣言内の識別子を見つけることです。識別子は変数の名前です。ここでは「d」です。

(私)
--「d」とは何ですか?
-------------------------------------------------- ----------------------
識別子の右側を見て、「[]」または「()」があるかどうかを確認します。
...d[]...: d は配列です。
...d()...: d は関数です。

どちらでもない場合は、左側に「*」があるかどうかを確認します。
...*d...: d はポインタです。
-------------------------------------------------- ----------------------

これで、d が関数であることがわかりました。x を使用して d() を置き換えると、宣言は「double (*x)[n]」になります。

(ⅱ)
――「×」とは?
-------------------------------------------------- ----------------------
(i) を繰り返すと、x がポインターであることがわかります。
つまり、d はポインタを返す関数です。
-------------------------------------------------- ----------------------

y を使用して *x を置き換えると、宣言は「double y[n]」になります。

(ⅲ)
-  Yとは何ですか"?
-------------------------------------------------- ----------------------
(i) を繰り返すと、y が n 要素の配列であることがわかります。
つまり、d は n 要素の配列へのポインタを返す関数です。
-------------------------------------------------- ----------------------

z を使用して y[n] を置き換えると、宣言は「double z」になります。

(四)
-- 「z」とは何ですか?
-------------------------------------------------- ----------------------
(i) を繰り返すと、z が double であることがわかります。
つまり、d は、n 個の double 要素の配列へのポインターを返す関数です。
-------------------------------------------------- ----------------------

別の表現を見てみましょう:

ボイド (*(*f)(int)[n])(char)
1.
  f を見つけます。
2.
  f はポインタです。*f -> a
  void (*a(int)[n])(char)
3.
  a は関数です。a() -> b
  ボイド (*b[n])(文字)
  --f は関数へのポインターです (int パラメーターを使用)--
4.
  b は配列です。b[] -> c
  ボイド (*c)(文字)
  --f は (n 要素の) 配列を返す関数へのポインタです --
5.
  c はポインタです。*c -> d
  ボイド d(文字)
  --f は、n 個のポインタの配列を返す関数へのポインタです--
6.
  d は void を返す関数です。
  --f は、void を返す関数 (char パラメータ付き) への n 個のポインタの配列を返す関数へのポインタです--
于 2012-11-06T09:37:53.297 に答える
1

「C 意味不明」を理解するには、次の 2 つの優れたリソースがあります。

cdecl.org の出力:

  • double (*c[n])(): 構文エラー (nここでは無効です)
  • double (*c[])(): double を返す関数へのポインタの配列として c を宣言します
于 2012-11-06T09:09:17.957 に答える