プロが教えるわが家の防犯対策術!

Pythonでの下記のクロージャを使ったカウンターの例をC言語で書くとしたら、
どの様に書くのが一番良いのでしょうか?

def gen_fnc():
  x = 1
  def hoge():
    nonlocal x
    print(x)
    x += 1
  return hoge

h = gen_fnc()
h() # 1
h() # 2
h() # 3

後、C言語の関数にはクロージャの機能は無いという理解で良いのですよね?

質問者からの補足コメント

  • どう思う?

    No.2さんの例では、クロージャを「状態を表す構造体」と「関数へのポインタ」
    を要素とする構造体で表現していますが、引数に状態を保持した関数として表現
    するのとどちらが良いのでしょうか?

    No.3の回答に寄せられた補足コメントです。 補足日時:2022/03/13 02:26

A 回答 (4件)

クロージャーとは、状態と紐づいた関数です。



ご提示の処理の場合は、
スコープ内の変数 x を状態として紐づいた関数がクロージャーです。

言語仕様にクロージャーが無い場合は、
関数の引数に状態を渡すことで疑似的に紐づけましょう。

/* 状態を表す構造体 */
typedef struct { int x; } counter_t;

/* 第1引数に状態を指定 */
int counter(counter_t* self, int n) {
_ self->x += n;
_ return self->x;
}

void main() {
_ counter_t p = { 1 }; /* 状態を生成 */
_ counter(&p, 1); /* 状態と紐づいた関数実行 -> 2 */
_ counter(&p, 2); /* 状態と紐づいた関数実行 -> 4 */
_ counter(&p, 3); /* 状態と紐づいた関数実行 -> 7 */
}
この回答への補足あり
    • good
    • 0

厳密な意味でのクロージャーを実現するならば状態と関数ポインタの両方を保持しましょう。

ただし厳密な実装を目指すとなると使い勝手が悪くなりがちです。

クロージャーっぽく便利に書きたいだけなら状態のみに留めましょう。できることに制限はありますが使い勝手は悪くないので実用的です。
    • good
    • 0

C言語でクロージャ:


https://nihemak.hatenablog.com/entry/20100215/12 …

> 後、C言語の関数にはクロージャの機能は無いという理解で良いのですよね?

ないです。
    • good
    • 0

クロージャについてあまり詳しくはありませんが、C言語はオブジェクト指向言語ではないので、同じことを実装するなら構造体を用いれば可能ですね。

    • good
    • 2

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!