2013-12-11

C++03とC++11の違い: 式編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

今回は式(expression)について。

C++11では、整数の除算と剰余の丸め方向がゼロに向かう。

これはC99との互換性を向上させるための変更である。

C++03では、 整数a, bに対して、a / b の結果が、実数では0.9とか-0.9になった場合、整数の結果の丸め方向がどちらになるのか規定されていなかった。

9 / 10 ; // 0? 1?
-9 / 10 ; // 0? -1?

C++03では、整数a, bで、a, bが、片方、あるいは両方とも正の整数でない場合、a % bの符号は実装依存だった。

3 % 2 ; // 1
-3 % 2 ; // 1? -1?
3 % -2 ; // 1? -1?
-3 % -2 ; // 1? -1?

C++03では、C言語の規格策定で、ISO Fortran 90、つまりISO/IEC 1539:1991の仕様に合わせるのが推奨されていると注記している。

Fortran 90規格の文面によれば、除算の商は、必ずゼロ方向に丸められる。

 9 / 10 ; // 0
-9 / 10 ; // 0

剰余の符号は、以下のようになる。

 8 %  5 ;    //  3
-8 %  5 ;    // -3
 8 % -5 ;    //  3
-8 % -5 ;    // -3

C99はFortranに合わせるによう規定され、C++11でも、C99との互換性向上のため、この規定に合わせることにした。

それにしてもわからないのが、未定義動作となる条件だ。a / bの商が式の結果の型で表現可能ではない場合というのはいいとしても、(a/b)*b + a%bがaと等しくない場合というのは、どうやったら可能になるのかわからない。そういうハードウェアがあるのだろうか。

参考文献:GFortranStandards - GCC Wiki

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

2 comments:

Anonymous said...

C89では、(a/b)*bはシーケンスポイントを含まないので、括弧があるにも拘わらず処理系は a*bを先に計算するよう最適化しても良い→a,bがintのとき、a=4,b=3として、a/bが先ならこの部分式の値は3、a*bが先なら4になったような。しかも、最適化都合なので、同じソースに同じ処理系を同じ最適化オプションでコンパイルしても、ソース中のある部分式は3に、別の部分式は4になってもよかったんでは。

典拠だせなくてすみません。

Anonymous said...

Fortran90の剰余演算にはMODとMODULOの二つがあり、負数の丸めの方向が異なります。