マクロの2重定義

  • 投稿日:
  • by
  • カテゴリ:



redefのウォーニングは何を説明しているでしょうか。


テストプログラムを書きます。main.c



#define TEST_MACRO (1)

#include <stdio.h>

int main()
{
printf( "TEST_MACRO is %d \n", TEST_MACRO );
return 0;
}

$ gcc -o test1 main.c
$ ./test1
TEST_MACRO is 1

マクロをコマンドラインで指定しても、、



$ gcc -o test2 -DTEST_MACRO=2 main.c
main.c:2:1: warning: "TEST_MACRO" redefined
<command line>:6:1: warning: this is the location of the previous definition
$ ./test2
TEST_MACRO is 1

ウォーニングを良く見てください。



<command line>:6:1: warning: this is the location of the previous definition


<コマンドライン>:6行目1桁目 警告:これは前に定義された場所です



プログラム中の#defineマクロ定数を-Dオプション指定で上書きすることはできないのです。


プログラムを変えてみれば、すぐに分かることです。



#define TEST_MACRO (1)
#define TEST_MACRO (2)

#include <stdio.h>

int main()
{
printf( "TEST_MACRO is %d \n", TEST_MACRO );
return 0;
}

$ gcc -o test3 main.c
main.c:2:1: warning: "TEST_MACRO" redefined
main.c:1:1: warning: this is the location of the previous definition

yasuda@R3 ~/src
$ ./test3
TEST_MACRO is 2

後の定義の値が使われます。これは処理系依存でgccのオプション指定の仕方次第なのかもしれません。それでもこれらの短い書き捨てプログラムを書けば良いだけです。暗記は必要ありません。しかし勝手な思い込みは避けなければなりません。


また、redefを利用したトリック実装も避けなければなりません。


異なった値で2重定義をおこなえば、#includeを書く順序で結果が異なるからです。


redefはエラーとできるなら、そうすべきでしょう。


ちなみに#defineを文字列置換だと勘違いしている人が世の中には多数居ます。


実際にはプリプロセッサのパーサで解釈された文脈の中でのみ有効です。


例えばこんなプログラム断片。



#define FUNNY_MACRO (0x55aa)

int main()
{
printf( "FUNNY_MACRO is used by strange people.\n" );
}
・・・

この文字列定数が置換されないのは言うまでもありません。


どんな処理系でも細かい話はいくらでもあります。ですが、覚えておくべきことは少ないです。少しでも不安なのであれば、試してみることがもっとも重要です。