4

私はCでプロジェクトに取り組んでいます。特定のルールに基づいて、多くのコードを自動的に生成できることがわかりました。すなわち。C構造体だけを指定すると、それに基づいてコードを自動的に生成できます。私はそれができることを知っています、しかし私は前にそれをしませんでした。経験豊富なCプログラマーが、最小限のエンジニアリング作業でそのようなことを行う方法について、特定の指針を示したり、経験を共有したりできると便利です。

編集:非常に具体的に言うと、すべてを行うためにCでカスタムパーサーを作成する必要がありますか、それともこれに対処するためのより簡単な方法がありますか?

4

3 に答える 3

3

簡単な部分は、1:1 の構文置換に関係しています。

難しいのは、1 対 1 の構文置換以外の非常に意味のあることを行うことです。

マクロに頼りすぎると、認知ドリフト (でっち上げられた名前) の問題に遭遇します。つまり、独自の言語 (マクロ言語) を設計しているのに、コンパイラーと実行中のプログラムが別の言語を使用しているということです。単純なマッピングが新しい言語をより扱いにくくすることはありませんが、マクロがテキストのみの置換レベルで機能するため、単純なマッピングでさえすぐに複雑になります。

C++ を使用している場合、テンプレートを使用する方がはるかに優れたソリューションです。テンプレートは、マクロと同じ機能の多くを提供しますが、テンプレートは型システムの認識に取って代わるため、認知ドリフトの影響をあまり受けません。

C に似た言語構造の構文と意味が進化するにつれて、新しい言語は、純粋な C ソリューションに必要な反復コードの量の問題を「修正」しようとすることがよくあります。C に "近い" いくつかの新しい言語を学習してみてください。そうすれば、このコードの重複を減らす方法が理解でき、C での "生成" 作業のより良い選択につながるでしょう。

于 2012-09-25T22:31:21.423 に答える
2

私が見た効果的な方法の1つは、マクロ(よく嫌われるツール)を使用することです。#_nameマクロには、作業をはるかに楽にするのに役立つ2つの機能があります。パラメータを文字列に変換できるシングルハッシュ「#」と、"fieldName1"パラメータを他のものと連結できるダブルハッシュ「##」です。新しいものを拡張します。つまりSTRUCT_##_type##_str、次のように変換さSTRUCT_int_strれます。"%d"

まず、構造体または「説明」をマクロでラップします。つまり、独自のファイル(the-struct.def)にラップします。

STRUCT_BEGIN(s_my_struct)
  STRUCT_FIELD(int, fieldName1)
  STRUCT_FIELD(int, fieldName2)
  STRUCT_FIELD(int, fieldName3)
STRUCT_END(s_my_struct)

// Note that you can add more structs here and all will automatically get defined and get the print function implemented 

次に、構造体を処理する必要があるものを宣言または実装する場所で、マクロを異なる方法で定義できます。すなわち

#define STRUCT_BEGIN(_name) struct _name {
#define STRUCT_END(_name) };
#define STRUCT_FIELD(_type, _name) _type _name;

#include "the-struct.def"

// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD

構造体を出力する関数を作成します

#define STRUCT_BEGIN(_name) void print_ ## _name(struct _name *s) {
#define STRUCT_END(_name) }
#define STRUCT_FIELD(_type, _name) printf("%s = " STRUCT_##_type##_str "\n", #_name, s->_name); 
#define STRUCT_int_str "%d" /* this is to output an int */
// add more types...

#include "the-struct.def"

// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD
#undef STRUCT_int_str

他の用途としては、関数を自動生成してバイトをスワップするなどがあります。

ここで要点として小さな例を作成しましたhttps://gist.github.com/3786323

于 2012-09-25T22:22:00.800 に答える
2

C でメタプログラミングを行う比較的伝統的な方法の 1 つは、X マクロのような手法を使用することです。

本質的には、単純な C 構造体宣言を使用するのではなく、次のようなマクロを使用して完全に構造体を定義します。

BEGIN_STRUCT(pointf)
FIELD(float, x)
FIELD(float, y)
END_STRUCT(pointf)

これらの定義を、複数のインクルードに対するガードなしでヘッダー ファイルに配置します。

次に、生成する必要のある各コード (基本構造を含む) について、#define各メタ言語マクロ、#include定義ヘッダー、および#undefメタ言語マクロを再度実行します。

#define BEGIN_STRUCT(N) struct N {
#define FIELD(T,N) T N;
#define END_STRUCT(N) }
#include "definitions.h"
#undef BEGIN_STRUCT
#undef FIELD
#undef END_STRUCT
于 2012-09-25T22:30:38.743 に答える