公衆衛生警告の編集-この質問には、未定義の行動に関する誤った仮定が含まれています。受け入れられた答えを参照してください。
最近のブログ投稿を読んだ後、私はすべての標準を回避することの実用性について多くのことを考えてきました-CおよびC++コードの未定義の仮定。これは、符号なし128ビット加算を行うためにC++から切り取ったスニペットです...
void c_UInt64_Pair::operator+= (const c_UInt64_Pair &p)
{
m_Low += p.m_Low;
m_High += p.m_High;
if (m_Low < p.m_Low) m_High++;
}
これは明らかにオーバーフロー動作に関する仮定に依存しています。明らかに、ほとんどのマシンは適切な種類の2進整数をサポートできますが(おそらく32ビットチャンクなどから構築されます)、オプティマイザーがここで標準未定義の動作を悪用する可能性が高まっているようです。つまり、m_Low < p.m_Low
条件が通過できる唯一の方法は、m_Low += p.m_Low
オーバーフローの場合です。これは未定義の動作であるため、オプティマイザーは、条件が常に失敗することを合法的に判断できます。その場合、このコードは単に壊れています。
したがって、問題は...
未定義の動作に依存することなく、上記の合理的に効率的なバージョンをどのように書くことができますか?
適切な64ビットのバイナリマシン整数があるが、未定義の動作を可能な限り最悪の(または不可能な)方法で常に解釈する悪意のあるコンパイラがあると想定します。また、特別な組み込み、組み込み、ライブラリなど、それを行うためのライブラリがないと仮定します。
マイナーな説明を編集 します-これはオーバーフローを検出するだけでなく、m_Lowとm_Highの両方が2 ^ 64を法とする正しい結果になるようにすることでもあります。これも、標準では定義されていません。