32

私は次のことと同等のことをしたいと思います:

#define print_max(TYPE) \
#  ifdef TYPE##_MAX \
     printf("%lld\n", TYPE##_MAX); \
#  endif

print_max(INT);

現在、#ifdefまたはネストされたプリプロセッサ ディレクティブは、関数マクロで確認できる限り許可されていません。何か案は?

更新:これは不可能のようです。実行時にチェックするためのハックでさえ、達成できないようです。だから私は次のようなもので行くと思います:

#ifndef BLAH_MAX
#  define BLAH_MAX 0
#endif
# etc... for each type I'm interested in

#define print_max(TYPE) \
    if (TYPE##_MAX) \
       printf("%lld\n", TYPE##_MAX);

print_max(INT);
print_max(BLAH);
4

7 に答える 7

13

Boost Preprocessor ( Boost は全体として C++ ライブラリですが、C だけでなく C++ でも機能します) ライブラリは、この種のタスクに役立ちます。マクロ内で #ifdef を使用する (これは許可されていません) 代わりに、毎回異なるマクロを定義してファイルを複数回インクルードし、ファイルで #ifdef を使用できるようにするのに役立ちます。

次のコードは、max.c に保存されている場合、ファイルの先頭にある MAXES #define にリストされている各単語に対して必要な処理を実行する必要があります。ただし、プリプロセッサは浮動小数点を処理できないため、_MAX 値のいずれかが浮動小数点の場合は機能しません。

(Boost Processor は便利なツールですが、完全に簡単というわけではありません。このアプローチがコピー アンド ペーストよりも優れているかどうかを判断できます。)

#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST)

#if !BOOST_PP_IS_ITERATING

/* This portion of the file (from here to #else) is the "main" file */

#include <values.h>
#include <stdio.h>
#include <boost/preprocessor.hpp>

/* Define a function print_maxes that iterates over the bottom portion of this
 * file for each word in MAXES */
#define BOOST_PP_FILENAME_1 "max.c"
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES)))
void print_maxes(void) {
#include BOOST_PP_ITERATE()
}

int main(int argc, char *argv[])
{
    print_maxes();
}

#else

/* This portion of the file is evaluated multiple times, with
 * BOOST_PP_ITERATION() resolving to a different number every time */

/* Use BOOST_PP_ITERATION() to look up the current word in MAXES */
#define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES)
#define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX)

#if CURRENT_MAX
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld\n", (long long) CURRENT_MAX);
#else
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined\n");
#endif

#undef CURRENT
#undef CURRENT_MAX

#endif
于 2008-11-19T15:48:18.283 に答える
6

私は前にそれを試しました。問題は#、マクロパラメータを文字列化するためにすでに予約されていることです。#defineのようなプリプロセッサトークンとして解析されません。

于 2008-11-19T13:24:41.773 に答える
4

私が持っている唯一の解決策は不正行為です.定義のセットとして_XXX_MAXを持つ型のリストを作成し、それを使用します. プリプロセッサで自動化された方法でリストを作成する方法がわからないので、試しません。リストが長すぎず、あまり集中的に維持されないことを前提としています。

#define PRINT_MAX(type) printf("%lld\n", _TYPE##_MAX);
#define HAVE_MAX(type) _TYPE##_MAX // not sure if this works 


/* a repetitious block of code that I cannot factor out - this is the cheat */
#ifdef HAVE_MAX(INT)
#define PRINT_INT_MAX PRINT_MAX(INT)
#endif

#ifdef HAVE_MAX(LONG)
#define PRINT_LONG_MAX PRINT_MAX(LONG)
#endif
/* end of cheat */


#define print_max(type) PRINT_##TYPE##_MAX
于 2008-11-19T13:35:29.347 に答える
0

テンプレートとは異なり、プリプロセッサはチューリング完全ではありません。#ifdefマクロの内部は使用できません。唯一の解決策はprint_max、一致するものが_MAX定義されている型のみを呼び出すようにすることですINT_MAX。そうでない場合、コンパイラは確実に通知します。

于 2008-11-19T13:29:32.743 に答える
0

これを行う簡単な方法はありません。最も近いのは、次のような多数の IFDEF マクロを #define することです。

#undef IFDEF_INT_MAX
#ifdef INT_MAX
#define IFDEF_INT_MAX(X)  X
#else
#define IFDEF_INT_MAX(X)
#endif

#undef IFDEF_BLAH_MAX
#ifdef BLAH_MAX
#define IFDEF_BLAH_MAX(X)  X
#else
#define IFDEF_BLAH_MAX(X)
#endif

     :

多くのものが必要なので (複数の場所で役立つ可能性があります)、必要なときにいつでも含めることができる独自のヘッダー ファイル 'ifdefs.h' にこれらすべてを貼り付けることは非常に理にかなっています。「対象のマクロ」のリストから ifdef.h を再生成するスクリプトを作成することもできます。

次に、コードは次のようになります

#include "ifdefs.h"
#define print_max(TYPE) \
IFDEF_##TYPE##_MAX( printf("%lld\n", TYPE##_MAX); )

print_max(INT);
print_max(BLAH);
于 2009-09-02T03:35:55.887 に答える
0

#ifdef で ## 演算子が許可されていない場合ではないと思います。私はこれを試しました:

#define _print_max(TYPE) \
#ifdef TYPE \
printf("%lld\n", _TYPE); \
#endif

#define print_max(TYPE) _print_max(MAX##_TYPE)


void main() 
{
    print_max(INT)
}

それでも機能しませんでした (#ifdef TYPE が好きではありませんでした)。問題は、#ifdef が #define 引数ではなく、#defined シンボルのみを受け入れることです。それらは2つの異なるものです。

于 2008-11-19T13:01:51.817 に答える