RSS

 

RSS


プ:#ifdef #ifは使っちゃダメ

  • いわいまさか
  • at 2007/7/26 20:55:03

 この「#ifdef #ifは使っちゃダメ」は前々から思っていたことで、最近、あるソースに手を入れた際に思いを強くした。チャンネルに掲せようと冒頭部分が書きかけだった。

 それとは別に、時を同じくして、会社メンバー4人で昼食ソバを食べたときに「#ifの入ったソースはメンテがきつい」という若手Uの声。そこでの情報も加えつつ記事を完成。

 プログラミング、CやC++の話。#ifdef や#ifは使わないほうがいい。以下、思いつく理由をいくつか。

1.感覚的にダメ

 「#ifdefや#ifは使っちゃダメ、感覚的によくないとわかるじゃん」と言ってる人もいる。岩井も概ね、賛成。ある程度の期間、CやC++を使った結果、そういう結論にたどりついた。「そういうセンスを持たないといけない」とも。でもこれは主張としては唐突・乱暴なので、次項からはもう少し理論建てて。

2.C++の通常のシンタックスとは別世界

  #ifdef, #if はCやC++の通常のシンタックスとは別世界なところが怖い。コメント(/* */ や // )ならその部分を削ってしまってもコードとしては同じ。でも、#ifdefや#ifではそういうわけにはいかない。

 下の例は極端にヒドイ例。開きカッコと閉じカッコの数が一致してない。「こんなソース書かなければいい」と言っても、他人から譲り受けたソースでは、その点、何の確約もない。

int  weight_of_dragon(void )
{
   ・・・・・・・
   ・・・・・・・
   ・・・・・・・
#ifdef  DRAGON_FLAG

   ・・・・・・・
   ・・・・・・・
   ・・・・・・・
  return (10000);  // 龍の体重は10トン
}    // ここで関数が完結しているのかというと、そうでなく。

#else
  return(1); // 蛇の体重は1kg
}
#endif

 「ファイル中での登場行数を移動しよう、この関数は分類的に後ろの方に持っていこう」、なんて程度のことも気軽には編集できなくなる。この「あんまりいじれない感」がダメなところ。

 「少しでもいいコードにするために直して行こう」という気持ちにブレーキをかける。

3.コンパイル時、実行時に「死んだ」部分
 #ifdef #ifでコードが分かれているとどちらかを選択して、コンパイル、そして実行することになる。逆にいうと、選択されてない部分はコンパイルの洗礼も受けないし、実行時のデバッグにも回らない。

 これはもったいない。「コンパイルが可能だ」ということはある程度のコードの体裁を保っている。コンパイルしない側に関していうと、キーボードを押してしまって、ataaaaaaaaaaaaaaaとコードに間違って挿入されてもコンパイルエラーも出ない。

 また「実行していくことによって、信頼性を勝ち取っていく」ということに関して、選択されていない側はオイテケボリ状態だ。

/////

 方策はというと、「#ifdef #ifはできるだけ使わないようにしよう」と思うところから始めるのが良いかと。

 前出の若手によると、プログラミング言語のDでは、言語の仕様上、#ifdef や#if (というか、プリプロセッサ全部)がないとのこと。いやぁ~、そうだよねぇと納得。


  • コメント (10)
  • トラックバック (0)
トラックバックURL :
http://www.iwai-masaka.jp/tb.cgi/731

コメント

>。「そういうセンスを持たないといけない」と
も。でもこれは主張としては唐突・乱暴なので、次項からはもう少し理論建てて。

2,3を読んでも結局、
「使い方が下手なだけ」としか見えませんね。

「そういうセンスを持たないといけない」ではなく、「使いこなせるようなセンスを養うべき」
では無いでしょうか。

  • Posted by 通りすがり
  • at 2008/09/04 20:50:40

コメントありがとうございます。
使いこなそうという路線に沿って言い直してみると、「うまくない場合が多いので「使わない」という方針で整理してみよう」ということです。

  • Posted by いわいまさか
  • at 2008/09/04 23:57:09

使うのはいいですが、使ったら最後に消してすっきりさせましょう。(ノд`)
メンテするときはコンパイルオプションを確認したり、間違いの元になります。

じつは #ifdef の嵐のアプリを引き継いで泣いてます・・・
作った本人はもういないし・・・orz

しかも #ifdef 0 や #ifdef 1 なども登場して、いったいどっちが実行されるのやら・・・

愚痴スレすみませんでした・・・

  • Posted by (ノд`)
  • at 2009/08/13 10:26:00

愚痴ついでにもう一つ・・・

#ifdef のネストって・・・

  • Posted by (ノд`)
  • at 2009/08/13 11:00:53

(ノд`)さんの愚痴、ありがとうごうございます。「コンパイルオプション確認の手間」「関連する間違いの発動」「作った本人はもういない」・・・いやぁ、どれもやっかいです。
さらに「ソースいじるなよ的圧力(明示or暗黙)」が加わるときもあり。「地雷原は危険だから行くな」なんだろうけど、その前にまず「地雷を埋めるな」だと思う。

  • Posted by いわいまさか
  • at 2009/08/13 13:36:25

とんでもない暴論です。狭い世界にしか生きてない人でないとそんな意見が出てきません。
ハードウェア互換用、通信環境用、デバッグ用等幅広く利用出来ます。掲載してる例はただの初心者が作ったバグ同然の内容で参考にすら成りません。

  • Posted by 仕事人
  • at 2009/09/24 18:26:03

短絡的な考えですね^^;

仕事人さんの仰るとおり、さまざまなハードウェア互換用やOS互換用やデバッグ用などの互換として、使用しています。
これをOS毎、環境毎にソース管理をしていると、一つ修正を行うたびに、何倍もの作業が必要になって、非効率すぎます。

サンプルコードもバグの引き金になるような初心者の幼稚なコードであって、議論の対象にもなりません。

  • Posted by nanashi
  • at 2009/10/06 10:55:46

根本的な知識不足ですね。

#if などはプリプロセスであって本来コンパイルとは関係ありません。
CやC++のシンタックスと違うのは当然で、同じだったら意味がないです。

  • Posted by 通りすがり
  • at 2010/03/05 16:18:28

メンテできないコードは全部消して作り直しなさよ。。

  • Posted by とおりすがり
  • at 2013/11/23 22:43:21

私も色々なソースを見てきましたがifdefが悪とは思っていません。

メンテナンス性が落ちるというのは使い方の問題であって、それはifdefに限った話ではありません。

ifdefがメンテナンス性向上のために使われているコードなどを調べてみると目からウロコが落ちるかもしれませんよ。