現在 WindowsNT4.0 + Gcc for Win32(Cgywin20)でUNIX用コードをwindowsに移
植しょうとしているのですが,そこで,あるソースファイルでは,
/* main.c */
57: FILE *file_in = stdin;
58: FILE *file_out = stdout;
59: FILE *file_err = stderr;
とグローバル変数を宣言しているのですが,
gcc にかけると,
main.c:57: initializer element is not constant
main.c:58: initializer element is not constant
main.c:59: initializer element is not constant
make.exe: *** [main.o] Error 1
と言う風に怒られました.
/*c:/bin/cygwin-b20/H-i586-cygwin32/i586-cygwin32/include/stdio.h*/
ではつぎのように定義されていて,constantではないのですか?
#define stdin (_impure_ptr->_stdin)
#define stdout (_impure_ptr->_stdout)
#define stderr (_impure_ptr->_stderr)
どなたがご教授お願いいたします.
---
山本さん、こんにちは。
> /* main.c */
> 57: FILE *file_in = stdin;
> 58: FILE *file_out = stdout;
> 59: FILE *file_err = stderr;
> とグローバル変数を宣言しているのですが,
グローバルに宣言しているのが問題です。グローバルに宣言された変数は通常全
てのプログラムに先立って初期化されます(チョット表現が間違っているかも
(^_^;))。元々のUNIXではOSレベルでサポートされているため非常にシンプルな構造
体であったFILE構造体が別OSでは初期化のために追加処理が必要となる事がありま
す。その追加処理の部分が問題になっているのでしょう。例えばバッファメモリー用
にmallocを必要としているとかです。
何のためにわざわざ「グローバル」な変数を「グローバル」な「別名の変数」に
コピーしなければならないのか(-_-メ)、「自己ルール」に違反しますが(^_-)。解決
方法は簡単です(^○^)。以下のようにmain()内で最初にコピーするようにすれば良い
のです(^○^)。
/* main.c */
FILE *file_in;
FILE *file_out;
FILE *file_err;
int main(...)
{
file_in = stdin;
file_out = stdout;
file_err = stderr;
...
}
> 57: FILE *file_in = stdin;
> main.c:57: initializer element is not constant
> /*c:/bin/cygwin-b20/H-i586-cygwin32/i586-cygwin32/include/stdio.h*/
> ではつぎのように定義されていて,constantではないのですか?
> #define stdin (_impure_ptr->_stdin)
constantではありません。
もともとのUNIXでは
extern struct iobuf _iob[];
#define sstdin &_iobuf[0]
なので、constant(というか、リンケージエディタとローダが
処理できる)なのですが・・・。
scgywinでは標準入出力のエミュレーションの都合でここまでの
互換性が実現できなかったのでしょう。
ちなみに、リンケージエディタの能力の問題(?)で、
FILE *file_in = stdin;
がエラーになる処理系にであったことがあります。
(MELCOM COSMO900II OSはなんだったか忘れた)
_impure_ptr の初期化と、
file_in の初期化の、
順序に依存しているようですが、
・どのような順序を期待しているのですか?
・それをリンカにはどのように伝えましたか?
(リンカは「心を持たない」道具です)
エラーメッセージに出てきた言葉に気を取られるのは
痛いほど解りますが、このあたり考え落としていませんか?