この質問はそれほど具体的ではありません。 それは本当に私自身のCの強化のためであり、他の人も同様に役立つと思います。
免責事項:多くの人が「FPを実行しようとしている場合、関数型言語を使用するだけです。」と応答する衝動があることを知っています。他のCライブラリ、およびより多くの大きな共有ライブラリ用のスペースがあまりなく、多くの言語ランタイムをサポートしていません。さらに、動的メモリ割り当ては問題外です。
私たちの多くは、ラムダ式のためのこの気の利いたCマクロを見てきました。
_#define lambda(return_type, function_body) \
({ \
return_type __fn__ function_body \
__fn__; \
})
_
また、使用例は次のとおりです。
_int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });
max(4, 5); // Example
_
_gcc -std=c89 -E test.c
_を使用すると、ラムダは次のように展開されます。
_int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; });
_
だから、これらは私の質問です:
行int(* X);は正確に何を宣言しますか?もちろん、int * X;は整数へのポインタですが、これら2つの違いは何ですか?
使い古されたマクロを見てみると、最終的な___fn__
_は一体何をするのでしょうか?テスト関数void test() { printf("hello"); } test;
を書くと、すぐにエラーがスローされます。私はその構文を理解していません。
これはデバッグにとって何を意味しますか? (これとgdbを試してみるつもりですが、他の人の経験や意見は素晴らしいでしょう)。これは静的アナライザーを台無しにしますか?
この宣言(ブロックスコープで):
int (*max)(int, int) =
({
int __fn__ (int x, int y) { return x > y ? x : y; }
__fn__;
});
はCではなく、有効なGNU C.
2つのgcc
拡張を使用します。
ネストされた関数(複合ステートメント内の関数の定義)とステートメント式(({})
(基本的に値を生成するブロック)はCでは許可されず、GNU C.
ステートメント式では、最後の式ステートメントは構造の値です。これが、ネストされた関数__fn__
は、ステートメント式の最後に式ステートメントとして表示されます。関数指定子(__fn__
は、通常の変換によって関数へのポインターに変換されます。これは、関数ポインターmax
を初期化するために使用される値です。
ラムダマクロは2つのファンキーな機能を活用します。まず、ネストされた関数を使用して、関数の本体を実際にdefineします(したがって、ラムダは実際には匿名ではなく、暗黙的な___fn__
_を使用します変数(ダブルアンダースコアの名前はコンパイラーのために予約されているため、他の名前に変更する必要があります。したがって、おそらく_yourapp__fn__
_のようなものが良いでしょう)。
このすべては、GCC複合ステートメント内で実行されます( http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs を参照)、その基本形式次のようになります:
_({ ...; retval; })
_
複合ステートメントの最後のステートメントは、宣言されたばかりの関数のアドレスです。これで、int (*max)(int,int)
には単に複合ステートメントの値が割り当てられ、宣言された「匿名」関数へのポインターになりました。
マクロのデバッグはもちろん王室の痛みです。
_test;
_ ..少なくともここでは、「異なるタイプのシンボルとして再宣言されたテスト」を取得する理由については、GCCが(役に立たない)式ではなく宣言として扱っていることを意味すると思います。型なし変数のデフォルトはint
であり、関数としてtest
をすでに宣言しているため(本質的にはvoid (*)(void)
)、それを取得します。
しかし、これは想像力の広がりによって移植性がありません。
部分的な答え:興味のあるint(* X)ではありません。int(* X)(y、z)です。これは、(y、z)を取り、intを返すXという関数への関数ポインターです。
デバッグの場合、これは非常に困難です。ほとんどのデバッガーはマクロをトレースできません。ほとんどの場合、アセンブリをデバッグする必要があります。
int (*max)(int, int)
は、宣言する変数のタイプです。 intを返すmaxという名前の関数ポインターとして定義され、パラメーターとして2つのintを取ります。
__fn__
は関数名を指し、この場合は最大です。
答えがありません。プリプロセッサで実行した場合、ステップスルーできると思います。