12

マクロに渡された変数がポインタであるかどうかを確認する「いい」方法はありますか? 例えば

#define IS_PTR(x) something
int a;
#if IS_PTR(a)
printf("a pointer we have\n");
#else
printf("not a pointer we have\n");
#endif

アイデアは、これは実行時ではなくコンパイル時に行われるということです。変数がポインターであるかどうかに応じて、異なるコードが得られます。だから私は IS_PTR() が何らかの方法である種の定数式に評価されることを望みます。私はこの考えについて間違った方向に進んでいますか?

4

5 に答える 5

3

_Genericこの問題の多かれ少なかれ解決策を見つけました。

警告: 誤検知がトリガーされる可能性があります (以下の例を参照)。

#define __INTERNAL_CHECK_POINTER(x) _Generic((x),\
          int: 0,       unsigned int: 0,\
         long: 0,      unsigned long: 0,\
    long long: 0, unsigned long long: 0,\
        float: 0,             double: 0,\
  long double: 0,                       \
      default: 1)

/**
 * Determines whether the variable has likely a pointer type (but may be triggered false-positive)
 */
#define IS_LIKELY_A_POINTER(x) ((sizeof(x) == sizeof(void*)) && __INTERNAL_CHECK_POINTER(x) ? 1 : 0)

デモ:

char c = 0;
printf("c is a pointer: %s\n", IS_LIKELY_A_POINTER(c) ? "Yes" : "No");

unsigned long long l = 0;
printf("l is a pointer: %s\n", IS_LIKELY_A_POINTER(l) ? "Yes" : "No");

double d = 0.0;
printf("d is a pointer: %s\n", IS_LIKELY_A_POINTER(d) ? "Yes" : "No");

unsigned char* cp = 0;
printf("cp is a pointer: %s\n", IS_LIKELY_A_POINTER(cp) ? "Yes" : "No");

struct tm* tp = 0;
printf("tp is a pointer: %s\n", IS_LIKELY_A_POINTER(tp) ? "Yes" : "No");

char ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
printf("ia is a pointer: %s\n", IS_LIKELY_A_POINTER(ia) ? "Yes" : "No");

これは出力されます:

c is a pointer: No
l is a pointer: No
d is a pointer: No
cp is a pointer: Yes
tp is a pointer: Yes
ia is a pointer: Yes // false-positive!

あなた (私のように) 何らかのロギング (特定の変数の a を描画するかしないか*) を探していて、失敗しない結果を探していない場合は、これを試してみてください。役立つ場合があります。乾杯!

MSVC ではコンパイルされないことに注意してください。gcc/clang/etc を使用します。代わりに、またはこの条件を使用して独自のフォールバック実装を作成します。

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
    // use _Generic code
#else
    // ¯\_(ツ)_/¯
#endif
于 2019-02-14T21:07:45.400 に答える