Last update: Mon, 28 Dec 2009 21:36:26 JST
[サイトのトップ] [GNOME] [987 Boxster] [SW20 MR2] [About Me]+ とあるC言語環境で以下のようなソースを最適化レベルをあげてコンパイルしてみたら、 「変数は値を代入する前に参照される可能性がある」という警告がでた。
char foo( char* a, char* b ) { char d; d = 1; while ( *a != 空白文字 && (d = *a - *b) == 0 ) { a++; b++; } return d; }
+ aやbのNULLチェックは?とかいう突っ込みは置いておいて、 コンパイラのマニュアルにも書いてあったように、
while ( cond ) { body; }
+ が最適化レベルを上げると
if ( cond ) { do { body; } while ( cond ) }
+ になるのはいいとして、 condが論理演算子で結合されている式である場合のように、 必ずしもcond内の全ての変数が評価されるとは限らない状況なのに、 評価されるとみなされているのである。 この場合は、 d = *a - *bが必ず評価されるとみなされ、 ループ直前のd = 1が無駄なコードと解釈されるため 「dは代入される前に参照される可能性がある」と警告されるわけだ。 確かにd = 1が無ければ、 whileの最初の条件*a != 空白文字が成立しないと(つまり空白文字の場合)、 return dで不定値が返ることになる(実際に問題になるのは不定値がたまたま0だった場合)。 実際、 吐き出されたアセンブラソースからd=1は抜け落ちてしまっている上に、 *a != 空白文字が不成立の場合は即座に (初期化も代入もされていないために中身が何であるか分からない)dに相当するレジスタの内容を戻り値として採用している。
+ ちなみに、 d=1の代わりに定義時にchar d=1と初期化してあげれば、 正しくコンパイルされるようである。
+ 自分はコンパイラの最適化論については全くもって明るくないので、 これが最適化の手法として日常的かどうかは良くわからないが、 個人的には不具合とみなしたくなってくる。 まあ、 なぜ定義時に初期化せず、 わざわざ代入文を用いているのか、 と問われると返答に窮するのも事実だが....。 とりあえず、 コンパイラバージョンを上げて試してみなければ。
+
自分の無知というだけの話なら、
不勉強をただただ恥じるばかり、
ということになるなぁ。
+ ちょっとだけ触ってみたけど、 かなり面白そう。 でも、 本格的にいじるのはDQ5が終わってからだなぁ。
+
ようやくReal Stratが届いた。
とりあえずインストールのみ。
メールはこちらへ...[Hideki AWATA (llyr @(at) nifty .(dot) com)]
この日記は、GNSを使用して作成されています。