要約
このレッスンは、データとその型を扱うコースの第二単元を締めくくる。変数から、コンパイラが見張る定数までを結ぶ概念の連鎖を、整数の二進表現とその二つのオーバーフロー、近似としての実数と許容誤差、コードとしての文字、情報を失う型変換を経由して組み立て直す。そのうちどの言語でも通用することと C++ に固有のこととを分け、単元の未定義動作を、コンパイラが検出するもの、サニタイザが検出するもの、誰も検出しないものに分けてまとめる。まとめテストでは導入テストの技能を繰り返し、最後に単元全体を組み合わせる六つの挑戦課題で終わる。
学習目標
- 問題の各データについて、とりうる値、求められる精度、それに対して行う演算に応じて型を選び、その理由を述べる。
- 与えられたプログラムで表現の限界がもたらす結果を予測する。整数のオーバーフロー、浮動小数点の丸め、型変換による情報の損失である。
- 名前付きの定数と明示的な型変換を使い、それぞれの場合にコンパイラが何を確かめるかを説明する。
- 単元の未定義動作を見分け、それぞれについて何がそれを検出し、どう防ぐかを述べる。
- 単元で学んだことのうち、どの言語でも通用することと C++ に固有のこととを分ける。
単元で達成したこと
この単元は、すべてのデータは型とともにメモリに置かれ、その型がとりうる値、占める大きさ、許される演算を決めること、そしてそれらの限界が目に見える結果をもたらすことを教えようとした。その目的は、導入が既知とした事柄、すなわちコースのオプションによるコンパイルと実行の作業サイクル、書式付き出力、std::cin による読み込み、コンパイラのメッセージの読み方だけに頼って達成された。導入が問題を提起したときの四つの計算のプログラムは、今では一行ずつ説明でき、修正もできる。
変数とメモリ
レッスン 変数とメモリ は、変数とは名前と固定された型と変化する値をもつメモリの区画であり、型がその大きさを決め、sizeof がそれを測ることを確立した。初期化と代入を区別し、波括弧が損失のある変換を拒むことを示し、代入はコピーするのであって結びつけるのではないこと、置き換えられた値は失われることを教えた。そこから、交換のための補助変数が導かれる。プログラムの状態を変数の値の全体として定義し、それをトレース表で追う方法を教えた。名前の付け方の約束を定め、単元で最初の未定義動作、すなわち一度も値を与えられていない変数の読み出しで締めくくった。
整数とその表現
レッスン 整数とその表現 は、基数 10、2、16 の位取り記数法を教えた。型が ビットをもつことからその値の範囲を導いた。ビットパターンは 通りあり、符号なしでは から まで、符号付きでは 2 の補数によって から までを表し、負の数が正の数より一つ多い。二つのオーバーフローを区別した。符号なし整数のオーバーフローは を法とする算術であって定義されており(0u - 1 は に等しい)、符号付き整数のオーバーフローは未定義動作であって、サニタイザがそれを止める。符号付き整数と符号なし整数を比べると前者が変換されるので が偽になることを示し、最後に、データの予想される範囲に応じて整数型を選ぶ基準を与えた。
浮動小数点数
レッスン 浮動小数点数 は、実数が符号、指数、二進の仮数として保持され、そのため表現できる値は分母が 2 のべきである有理数の有限集合になることを示した。そこから、 は機械の中には存在しないことが導かれた。代わりに最も近い double の値が保持され、0.1 + 0.2 は 0.30000000000000004 と書かれる。このレッスンは丸めごとの誤差を上から押さえ、誤差が蓄積すること、加法が結合法則を満たさなくなることを示した。そこから、計算された二つの実数は == ではなく、根拠のある許容誤差を用いてその距離で比べることを導いた。double を既定の実数型と定め、無限大と非数 NaN を紹介した。
文字・真偽値・型変換・定数
レッスン 文字・真偽値・型変換・定数 は、型とはビットを読む規則であることを示した。char は 1 バイトを保持し、その値は文字の ASCII コードであり、数字と文字は連続したコードをもつので '7' - '0' は 7 である。bool は真か偽であり、0 でないどんな数も真に変換される。暗黙の型変換を調べ、変換は結果を保存するときではなく、演算の中で、オペランドの型に従って起こることを確立した。double r{7 / 2} の値は 3 である。意図した変換を static_cast で書くことを教えたが、これは損失を防ぐのではなく宣言するものである。波括弧が縮小変換を拒むことを明確にし、単元で三つ目の未定義動作、収まらない実数の整数への変換を示した。最後に定数(const、constexpr、static_assert)、リテラルの型、auto を扱った。
コンテンツを読み込んでいます…