web-dev-qa-db-ja.com

Cの入れ子関数

Cでネストされた関数を使用できますか?ネストされた関数の使用とは何ですか? Cに存在する場合、それらの実装はコンパイラごとに異なりますか?

80

標準Cの別の関数内で関数を定義することはできません。

関数内で関数をdeclareできますが、ネストされた関数ではありません。

gccには ネストされた関数を許可する言語拡張機能 があります。それらは非標準であるため、コンパイラーに完全に依存しています。

94
James McNellis

いいえ、Cには存在しません。

(少なくとも)次の2つの理由で、Pascalのような言語で使用されます。

  1. 名前空間を汚染することなく、機能を分解できます。 1つ以上のネストされた関数を使用して問題をより小さな論理要素に分割することにより、いくつかの複雑なロジックを実装する単一の公開関数を定義できます。
  2. 場合によっては、パラメータの受け渡しを簡素化します。ネストされた関数は、外部関数のスコープ内のすべてのパラメーターと一部またはすべての変数にアクセスできるため、外部関数はネストされた関数にローカル状態の山を明示的に渡す必要はありません。
32
Marcelo Cantos

入れ子関数はANSI Cの一部ではありませんが、 それらは一部です Gnu C

18
zoli2k

いいえ、Cにネストされた関数を含めることはできません。最も近い方法は、別の関数の定義内で関数を宣言することです。ただし、その関数の定義は、他の関数本体の外部に表示される必要があります。

例えば。

void f(void)
{
    // Declare a function called g
    void g(void);

    // Call g
    g();
}

// Definition of g
void g(void)
{
}
15
CB Bailey

Cでコーディングしている多くの人が現在C++コンパイラ(Visual C++やKeil uVisionなど)を使用しているため、これについて言及しています。

Cではまだ許可されていませんが、C++を使用している場合は、C++ 11で導入されたラムダ関数で同じ効果を実現できます。

void f()
{
    auto g = [] () { /* Some functionality */ }

    g();
}
5
Jon Green

他の人が答えたように、標準Cはネストされた関数をサポートしていません。

一部の言語では、ネストされた関数を使用して複数の関数と変数をコンテナー(外側の関数)に囲み、個々の関数(外側の関数を除く)と変数が外部から見えないようにします。

[〜#〜] c [〜#〜]では、このような関数を別のソースファイルに入れることでこれを行うことができます。メイン関数をグローバルとして定義し、他のすべての関数と変数をstaticとして定義します。これで、メインモジュールのみがこのモジュールの外側に表示されます。

2
PauliL

2番目の質問に答えるには、ネストされた関数を定義できる言語があります(リストは nested-functions-language-list-wikipedia )。

これらの言語の中で最も有名なJavaScriptの1つである、入れ子関数(クロージャーと呼ばれる)の使用法は次のとおりです。

  • オブジェクトのコンストラクターでクラスメソッドを作成します。
  • セッターとゲッターとともにプライベートクラスメンバーの機能を実現するため。
  • グローバルな名前空間を汚染しないこと(もちろん、すべての言語に当てはまります)。

いくつか例を挙げると...

1
kyriakosSt

または、あなたはそれについて賢く、あなたの利点でプリプロセッサを使用することができます(source.c):

#ifndef FIRSTPASS
#include <stdio.h>

//here comes your "nested" definitions
#define FIRSTPASS
#include "source.c"
#undef FIRSTPASS

main(){
#else
    int global = 2;
    int func() {printf("%d\n", global);}
#endif
#ifndef FIRSTPASS
    func();}
#endif
0