QA@IT

Cで指定された範囲内に書かれたある関数を別の関数にすげ替えられるマクロを書きたい

3279 PV

Cのマクロと条件付きコンパイルを利用して、指定された範囲に書かれた関数を別の関数に置き換えられる(置き換えないようにもできる)書き方を知りたいです。

置き換えたい関数ごとにマクロを使えば、例えば以下のように実現できることはできます。

#include <stdio.h>

#ifdef USE_NEW_FUNC
#define NEW(func) (new_##func)
#else
#define NEW(func) (func)
#endif /* USE_NEW_FUNC */

void new_foo1(){printf("new foo1\n");}
void new_foo2(){printf("new foo2\n");}

void foo1(){printf("normal foo1\n");}
void foo2(){printf("normal foo2\n");}

int main() {
  foo1();
  foo2();

  NEW(foo1());
  NEW(foo2());
}

とはいえ、各行に直接USE()と書かないといけないためあまりうれしくないので、できれば以下のように書きたいのです。

/* 例その1 */
int main() {
  foo1();
  foo2();

  NEW_FUNC_BEGIN
  foo1();
  foo2();
  NEW_FUNC_END
}

/* 例その2 */
int main() {
  foo1();
  foo2();

#define USE_NEW_FUNC 1
  foo1();
  foo2();
#undef USE_NEW_FUNC
}

このような書き方で上記と同様のことを実現することは可能でしょうか?
(単純に考えると2passじゃないとできないような気がするのですが、どうにかならないものかなあ、というところです。)

回答

#pragma push_macroを使うというのはどうでしょうか。非標準の機能なのでサポートしていないコンパイラがあるかもしれませんが、個人的にはそのようなものは見たことがありません。

#include <stdio.h>

#define NEW_FUNC_BEGIN \
    _Pragma("push_macro(\"foo1\")"); \
    _Pragma("push_macro(\"foo2\")")
#define NEW_FUNC_END \
    _Pragma("pop_macro(\"foo2\")"); \
    _Pragma("pop_macro(\"foo1\")")

void new_foo1(){printf("new foo1\n");}
void new_foo2(){printf("new foo2\n");}

void foo1(){printf("normal foo1\n");}
void foo2(){printf("normal foo2\n");}

int main() {
  foo1();
  foo2();

  NEW_FUNC_BEGIN;
#define foo1() new_foo1()
#define foo2() new_foo2()
  foo1();
  foo2();
  NEW_FUNC_END;
}

編集 履歴 (0)
  • ありがとうございます! #pragmaはよく知らないので調べてみます。 -

標準の機能だけだと毎回 #define NEW しなおせば可能そうです。

#include <stdio.h>

#define NEW(func) (func)
#define foo1 NEW(foo1)
#define foo2 NEW(foo2)

void foo1(void) { puts("foo1"); }
void foo2(void) { puts("foo2"); }
void new_foo1(void) { puts("new_foo1"); }
void new_foo2(void) { puts("new_foo2"); }

int main() {
  foo1();
  foo2();

#undef NEW
#define NEW(func) (new_##func)
  foo1();
  foo2();
#undef NEW
#define NEW(func) (func)

  foo1();
  foo2();
}
編集 履歴 (0)
  • ありがとうございます! なるほど、こういう方法もあるんですね……。思いつきませんでした。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。