7

現在、既存のCライブラリをクリーンアップして、恥知らずに公開しています。

プリプロセッサマクロは、コンパイル時にNPOT特定の積分定数式の2の次に大きい累乗を計算するために使用されます。マクロは通常、直接初期化で使用されます。他のすべての場合(たとえば、変数パラメーターを使用する場合)、同じ関数を持つインライン関数があります。

しかし、ユーザーが変数を渡すと、アルゴリズムは巨大なマシンコードに拡張されます。私の質問は 、ユーザーが整数定数式以外のものをマクロに渡さないようにするにはどうすればよいですか?

#define NPOT(x)   complex_algorithm(x)

const int c=10;
int main(void) {
    int i=5;

    foo = NPOT(5);   // works, and does everything it should
    foo = NPOT(c);   // works also, but blows up the code extremely
    foo = NPOT(i);   // blows up the code also
}

私がすでに試したこと:

  1. マクロをに定義し#define NPOT(x) complex_algorithm(x ## u)ます。それはまだ機能し、変数パラメータに対して-ほとんど役に立たない場合でも-コンパイラエラーをスローします。iuのような変数がない限り...汚い、危険な、それを望まない。
  2. ドキュメントは、ほとんどのユーザーには機能しませんでした。
4

2 に答える 2

7

定数積分式を必要とし、最適化される任意の式を使用できます。

#define NPOT(X)                                         \
 (1                                                     \
 ? complex_algorithm(X)                                 \
 : sizeof(struct { int needs_constant[1 ? 1 : (X)]; })  \
 )

最終的には、の結果を適切な整数型にキャストする必要があるsizeofため、戻り式は期待どおりの型になります。

私はstructここでタグなしを使用しています

  • タイプがあるので、一時的なものは実際には生成されません
  • 競合を引き起こすことなく式をコード内のどこでも繰り返すことができるような一意のタイプを持っている
  • VLAの使用をトリガーします。これはstruct、C99の時点では許可されていません。

構造体または共用体のメンバーは、可変的に変更された型以外の任意のオブジェクト型を持つことができます。

三項演算子?:1選択式として使用して、:が常にその型に対して評価されるようにしますが、式として評価されることはありません。

編集: gccは内部structのVLAを拡張機能として受け入れ、明示的に言っても警告しないよう-std=c99です。これは本当に悪い考えです。

このような奇妙なコンパイラの場合はsizeof((int[X]){ 0 })、代わりに、を使用できます。これは上記のバージョンと同じように「禁止」されていますが、さらにgccでさえ不平を言っています。

于 2012-02-14T09:46:27.907 に答える
0
#define INTEGRAL_CONST_EXPR(x) ((void) sizeof (struct {int a:(x);}), (x))

xが整数定数式でない場合、これによりコンパイルエラーが発生します。

my_function(INTEGRAL_CONST_EXPR(1 + 2 + 3));    // OK
my_function(INTEGRAL_CONST_EXPR(1.0 + 2 + 3));  // compile error

このソリューションは、静的変数の初期化には機能しないことに注意してください。

static int a = INTEGRAL_CONST_EXPR(2 + 3);

,が定数式ではないため、コンパイルエラーが発生します。

@JensGustedtがコメントに書いているように、ビットフィールド幅を負にすることはできないため、負の整数に解決される整数定数式をこのソリューションで使用することはできません。

于 2012-02-14T09:48:35.183 に答える