2

プリプロセッサを使用して、 Cの一部の関数の動作を変更しようとしています。また、オンまたはオフに設定できるオプションのパラメータを追加します。

オプションのパラメータの基本的なパターンは簡単です。

#ifdef OPT_PARAM
  #define my_func(a, b, opt) _my_func(a, b, opt)
#else
  #define my_func(a, b, opt) _my_func(a, b)
#endif

/*the rest of the code always calls "my_func" with all the params
and not the underscored version...*/

#ifdef OPT_PARAM
void _my_func(int a, int b, int opt)
#else
void _my_func(int a, int b)
#endif
{
  /*... more #ifdefs surrounding opt uses */
}

関数を条件付きでラップするパターンは似ていますが、問題はアンダースコアが加算され始めることです(ネストのレベルごとに1つ余分に、異なる関数にすることも、ラップされていない場合は次のレベルの#defineにすることもできます)。 )。

では、ここでコードの複雑さを軽減する方法について何かアイデアはありますか?

PS私はPythonを使用したいと思います...しかしこれはドライバー用です:-(

4

4 に答える 4

2

C ++コンパイラを使用できますか?(C ++機能の)関数のオーバーロードだけを使用できます。

別のオプションは

#ifdef OPT_PARAM
#  define OPT(X) , X
#else
#  define OPT(X)  
#endif

int my_func(int a, int b OPT(int opt) ) {
#ifndef OPT_PARAM
  int opt = default_value;
#endif
  ... // Rest of code
}  


...
// calling it
my_func(2, 4 OPT( 42 ) );
于 2009-07-25T01:02:41.563 に答える
2

デフォルトの引数または C では使用できないものを使用したいようです。これは悪い考えのようです。引数を指定したくない場合は、単に NULL または -1 (標準) を渡すという、より C 的な方法で物事を処理してみませんか。

void function (int a, int b, int c) {
  if (c != -1) {
    // something
  }
}

function(a,b,-1);
function(a,b,c);
于 2009-07-24T15:55:40.687 に答える
1

これはあなたが望むものに近いかもしれないと思いますが、確信が持てません。私の理解では、任意の数の引数を持つc関数を許可し、型をチェックしてコンパイル時に削除できるという考えです。

標準を引用して、識別子でのアンダースコアの使用について警告させてください。予約済みの識別子に遭遇する場合があります。ただし、これの可能性は私にはわかりません。

ISO/IEC 9899:1999 (E) 7.1.3

— アンダースコアと大文字または別のアンダースコアで始まるすべての識別子は、常に使用のために予約されています。

このソリューションには GCC が必要です。GCC のバージョンは、ウィーク シンボルもサポートする必要があります。考え方は、コンパイラが弱いシンボルを使用して正しい関数定義を探せるようにすることです。さらに、関数の内容は、コンパイラがデッド ブランチをプルーニングする必要があるという知識を使用して単純化されます。つまり、次のようになります。

if (0) { ... }

さらに分析することなくコンパイル時に(GCC 4.xは確かにこれを行います)。存在しないオプション パラメータを C プリプロセッサ (cpp) シンボルとして定義することにより、関数本体に cpp 条件を含めることを回避できます (必要な場合)。以下の f_opt0 に対して opt1 と opt2 がどのように定義されているかを参照してください。

#include <assert.h>
#include <stdio.h>

extern void f_opt0(int a, int b) __attribute__((weak));
extern void f_opt1(int a, int b, int opt1) __attribute__((weak));
extern void f_opt2(int a, int b, int opt1, int opt2) __attribute__((weak));

#ifdef OPT0
void f_opt0(int a, int b) {
#define opt1 0
#define opt2 0
#endif
#ifdef OPT1
void f_opt1(int a, int b, int opt1) {
#define opt2 0
#endif
#ifdef OPT2
void f_opt2(int a, int b, int opt1, int opt2) {
#endif
  if (opt1) printf("opt1=%d\n", opt1);
  if (opt2) printf("opt2=%d\n", opt2);
  printf("a+b=%d\n", a+b);
  #undef opt1
  #undef opt2
}

#define f(a, b, o1, o2) \
  if (f_opt2) f_opt2(a, b, o1, o2); \
  else if (f_opt1) f_opt1(a, b, o1); \
  else if (f_opt0) f_opt0(a, b); \
  else { assert(0 && "no f() defined!"); }

int main(void) {
  f(1, 2, 1, 1);
  return 0;
}

私のテストは非常に限られており、これを C の優れた設計とは言いません。問題が発生しやすく、理解するのが面倒です。しかし、それがあなたの目標を達成することを願っています。

于 2009-07-25T00:40:23.273 に答える
0

最後に、余分なパラメーターを一様に処理する新しいデコレーターを追加し、あいまいなアンダースコアをよりわかりやすい名前に変更しました。

現在は、実行時のオーバーヘッドなしでコンパイル時に動作をプラグおよびアンプラグできる、より直交した設計になっています。

于 2009-07-27T16:34:34.067 に答える