パスワードを忘れた? アカウント作成
13346172 story
プログラミング

C++17では非推奨だったbool型に対するインクリメント演算子の利用が不可能に 65

ストーリー by hylom
そもそもの挙動が分かりにくい感じ 部門より

C++言語の新標準規格である「C++17」では、bool型に対する++演算子が利用できなくなるそうだ(cpprefjp - C++日本語リファレンス)。今まではbool型の変数に対し++演算子を適用すると、その変数の値をtrueにするという仕様となっていた。

なお、C言語にはbool型が存在しないため、int型をbool型の代用として使用することが良くあった。この場合、C++の仕様と同様に++演算子を適用するとその値は必ず1以上、つまりtrueになるように見える。しかし、変数の値がint型に格納できる最大値(たとばintが8ビットの場合255)になっていた場合、++演算子を適用するとオーバーフローが発生してその値は0、つまりfalseになってしまうという問題があった。

cpprefjp - C++日本語リファレンスによると、放射線療法機器「セラック25」ではこのバグが原因で死者を出す事故が発生していたという。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • セラック25 (スコア:3, 興味深い)

    by Anonymous Coward on 2017年07月20日 19時33分 (#3247538)

    Cではなくアセンブリ言語で書かれていたようです。
    https://en.wikipedia.org/wiki/Therac-25 [wikipedia.org]
    アセンブリ言語ならこういう書き方をするのもわかる気がしますが、
    そのバグがC++の仕様に影響を与えていたとは。。。

  • by manmos (29892) on 2017年07月20日 17時30分 (#3247487) 日記

    _Bool型あります。

    _Bool a,b;
    a = 1;
    b = a+a;

    printf(("%d\n",b);
    printf(("%d\n",(_Bool)(-1));

    は共に1を表示します。

    • by Anonymous Coward on 2017年07月20日 17時39分 (#3247490)

      gccはかなり成績いいけど、
      もうちょっとマイナーなccの_Boolを本気でアラ探しすると、
      結構面倒なこと [ludd.ltu.se]になるよ

      親コメント
    • Re: (スコア:0, 荒らし)

      by Anonymous Coward

      gccのboolって、結局8bit or 16bit intでなかったでしたっけ?

      数年前、On/Offのフラグを320万個くらい確保しなくてならなくて
      必要なメモリ確保量に悲鳴を上げた覚えが。
      それならint型で配列確保するがな。

      boolって、それを1bitで実現できるから便利なんだと思いましたですよ。
      #結局、8bit charを分解して1bitごとのbool代数にするライブラリを
      #独自開発して繰り延べ。
      #そういや、ユーザがこのストーリーにある「++」演算子をする可能性は全く考えてなかったw
      #まあ、俺が開発して俺が使うライブラリだからいいっかー

      • by Anonymous Coward on 2017年07月20日 22時46分 (#3247665)

        そうです。C++のboolもC99のboolも、&演算子でアドレスを取得できる必要がある、という理由で、1バイト以上の大きさが必須となっています。

        ビット単位でのストレージは、C++ならクラス作ってなんとかしろということで、std::bitset<>、std::vector<bool>、boost::dynamic_bitsetなどが生まれましたね。

        親コメント
  • by osdn (47242) on 2017年07月20日 17時15分 (#3247474)

    その挙動に依存していたせいで、修正後さらに死者を出すような事態にならないことを祈る

    • by Anonymous Coward

      なくなるんだから、依存課所はコンパイルエラーになるんとちゃうの?

      #PHPではならないから地獄。Web専用言語のくせに全部実行時エラーとかアホか。

      • by Anonymous Coward

        上でも書かれてるように、intに#defineなりtypedefなりって修正をするとエラーを吐かなくなるから……

    • by Anonymous Coward

      ん?ポロリするのは256回に1回では?

  • by Anonymous Coward on 2017年07月20日 21時13分 (#3247604)

    falseや#f、nilのような特殊なシンボル以外は、あらゆる値が真扱いでいいだろ
    下手にtrueとか無駄な状態を作ろうとするからおかしなことになるんだよ
    なにがオーバーフローだよ、知らねえよバカ
    #fじゃねえんだったら、値がゼロだろうがマイナスになろうが変数がまだ未初期化だったとしても黙って真を返して来りゃいいんだよ

  • by Anonymous Coward on 2017年07月20日 17時22分 (#3247480)

    Javaはこういうアホな仕様を排除してて良いんだよね。

    • by Anonymous Coward on 2017年07月20日 17時50分 (#3247493)

      オブジェクト同士の == が参照が同じかどうか比較というアホな仕様をどうにかしてくれませんかね。

      親コメント
      • by Anonymous Coward

        (Cでいう)ぽぽぽポインタの比較だから!あ、あってるから!

        • by Anonymous Coward

          普通equls()を使うよな。使うというか作るのだが。オーバーライドセずにそのまま使うと==と同じことになるし。ま、オブジェクトは==を使えないようにして参照先の比較はcheckPointer(obj1,obj2)とかにすればもっとよかったんだろうけど。
          初心者はStringとStringを==で繋いじゃうんですよねー。=でつなぐ人もいますけど。まぎらわしーよねー。

          • by Anonymous Coward on 2017年07月20日 19時47分 (#3247544)

            Javaは演算子オーバーライドできない仕様だったから、そうなっちゃった。
            C#は最初から演算子オーバーライドできるから、文字列の==は直感的な仕様になってる。

            親コメント
          • by Anonymous Coward on 2017年07月20日 20時47分 (#3247584)

            初心者はStringとStringを==で繋いじゃうんですよねー。=でつなぐ人もいますけど。まぎらわしーよねー。

            ある程度、熟練してても、VB.NETとC#を交互につかうと間違えそうになる。

            # 逆にド初心者というか、プログラミングやってない人だと
            # i = i + 3;
            # みたいな式を見て「!?」となるとか

            親コメント
          • by Anonymous Coward

            初心者はjava.lang.String#intern()を知りませんからね...。

    • by Anonymous Coward on 2017年07月21日 2時07分 (#3247715)

      演算子オーバーロードを排除したがために、BigInt等の計算がむごいことになってるがな。

      まあ理由はフールプルーフの類だが、
      「使う人の問題」を言語でなんとかしようとするのは程々にしとくもんだよ。

      ※あまりにクソな奴は無視しろ!と思うがそういう奴ほど声デカくてうざいんだよねーw

      親コメント
      • by Anonymous Coward

        だからSIerにはJavaのウケがいいのか

    • by Anonymous Coward

      C#: せやな
      PHP: せやせや
      PL/I: 笑止

      • by Anonymous Coward

        JavaScript: お、===(厳密等価演算子)ぶつけんぞ

  • by Anonymous Coward on 2017年07月20日 20時25分 (#3247567)

    VB「-1ぞ」

    • by Anonymous Coward

      COM で使われる VARIANT_TRUE も 0xFFFF だから -1 ですな

      • by Anonymous Coward

        VARIANTとかSAFEARRAYとかはVBの型の一部を他言語で使えるように切り出したようなものだからな。

    • by Anonymous Coward

      Microsoft Basicから-1でしたね。

  • by Anonymous Coward on 2017年07月20日 20時46分 (#3247583)

    ++する事で0と1が切り替わるのかと
    int型→bool型に置き換えた場合に不具合がでないように今の仕様になったんですかね

    • by Anonymous Coward

      たぶんそうですな。最初からboolでやる人はインクリメントなんかせず絶対代入にするもん。

      bool代用でint使うなら普通0か1かですよね…いくら判定がif(a!=0)と扱われるとしてもtrue/false相当とした数字以外に平気でなる組み方はさすがにどうかと。

      • by Anonymous Coward

        でも、JavaScriptでも似たようなことを無意識でやってる人は多いと思う。

        function sortWords(aStr) {
          var str = "";
          var a = aStr.split(" ").sort();
         
          while (a.length) {
            str += a.shift() + " ";
          }
          return str;
        }
         
        alert(sortWords("Orange Apple Banana"));

  • by Anonymous Coward on 2017年07月21日 7時45分 (#3247761)

    int型をインクリメントしてboolに変換してたんだから、boolのインクリメントが禁止されても防げなくない? 逆に変数がbool型で宣言されていたらインクリメントしても問題なかった(確実にtrueになることが保証される)。なんでこのバグをC++17の仕様変更と関連付けてるのかまったく意味がわからない。

    • by Anonymous Coward
      書いてあることも理解できてないようなので、文章を読むときに書いてあることだけでも理解する癖をつけたほうがいいぞ。
typodupeerror

一つのことを行い、またそれをうまくやるプログラムを書け -- Malcolm Douglas McIlroy

読み込み中...