Main Content

C コード生成製品によるシフトの使用

コード生成製品によるシフトの紹介

MATLAB® Coder™Simulink® Coder および Embedded Coder® は、C 言語の左シフト (<<) と右シフト (>>) 演算子を使用する C コードを生成します。最新の C コンパイラでは、シフト演算で整合性のある動作が行われます。ただし、シフト演算子の動作のいくつかは一部の C 規格で完全に定義されていません。The MathWorks® のコード生成製品を使用する場合は、C シフトの使用を管理する方法を理解しなければなりません。

2 の補数

2 の補数は 2 進数を解釈する方法の 1 つです。ほとんどの最新プロセッサは、2 の補数を使用して整数を表します。MathWorks® の C コード生成製品で 2 の補数を使用して符号付き整数を表すには、C および C++ コンパイラが必要です。MathWorks ツールボックスおよびドキュメンテーションでは 2 の補数表現を排他的に使用します。

算術シフトと論理シフト

算術シフトと論理シフトの主な違いは目的です。算術シフトは数学的な意味をもちます。論理シフトの目的は、ビットを移動し、ビット フラグの集合として使用されている符号なし整数に対してのみそれらのビットを有効にすることです。

C 言語では、算術シフトと論理シフトが区別されず、シフト演算子の 1 つのセットのみ提供されます。MathWorks のコード生成製品が生成されたコードの符号付き整数でシフトを使用する場合、目的は常に算術シフトになります。符号なし整数の場合は、論理シフトと算術シフトの動作に検出可能な違いはありません。

左シフト演算

左シフト演算は 2 のべき乗による乗算を表します。

a << b = a*2^b

2^b による乗算で算出された値が大きすぎる場合、オーバーフローが発生します。オーバーフローが発生すると、イデアル解はデータ型に合うように 2^n を法としてラップ アラウンドします。C90 規格では、左シフトの動作を指定しています。ビット レベルで、ビットの b は左端からシフトされて、破棄されます。右端では、値 0 の b ビットがシフトされます。この規格では、符号なしと符号付きの違いは指定されていません。符号なしと 2 の補数の符号付きの両方で、ビット レベルの動作は意図された左シフト演算の動作になります。

C99 規格では、演算の解釈を説明しています。この規格では、符号付き型の場合、負の値またはオーバーフローになる正の値の動作は未定義であることも示しています。コンパイラ ベンダーは C99 規格の未定義の動作に関する節を利用して、コード生成製品が意図する動作が変更されるようにコードを最適化する場合があります。コンパイラが C99 に準拠していても C90 に準拠していない場合は、オプションReplace multiplications by powers of two with signed bitwise shifts (Embedded Coder)をオフにしてください。古い C++ 規格は、左シフトに関する C90 規格に準拠します。新しい C++ 規格は C99 規格に似ています。

右シフト演算

右シフト演算は 2 のべき数による除算を表します。この場合、イデアル商では負方向の丸めが行われます。

a >> b = a/2^b

C 規格では、a が非負である場合、右シフトでこの演算動作が示さなければならないことが規定されています。a が符号付きで負の場合は、実装によって動作が定義されることが規定されています。C 規格では、コンパイラで実装動作を記述する必要があります。ほぼすべてのコンパイラが、符号付き右シフトを負方向の丸めを行う演算として実装します。これは、コンパイラ ベンダーが提供するのに最も簡単で効率の良い動作です。右シフト演算を提供しないコンパイラがある場合またはコーディング規格で符号付き右シフトの使用が許可できない場合は、符号付き右シフトを回避するオプションを選択できます。たとえば、Allow right shifts on signed integers (Embedded Coder)では符号付き右シフトが関数の呼び出しに置き換えられます。

範囲外シフト

C では、語長 n の整数をシフトする場合、0 から n – 1 まで (これらの値を含む) のシフト量を使用します。C 規格では、次のような他の量によるシフトを定義していません。

  • 負の定数によるシフト。

  • 語長よりも大きい量によるシフト。

シフト量が定数の場合、製品は範囲外のシフトを生成しません。範囲外のシフトのリスクは、シフト量が非定数変数である明示的にモデル化されたシフトから生じます。可変シフト量でシフトをモデル化する場合は、シフト量が常に範囲内に収まるようにしてください。

シフトのソースのモデル化

モデルとアルゴリズムには、シフトの明示的ソースと暗黙的ソースがあります。

明示的

暗黙的

  • スケーリングの変更を含む固定小数点演算

    固定小数点のスケーリングを変換するときに、正味勾配の変更が正確な 2 のべき乗でない場合、シフトが後に続く乗算でイデアル正味勾配を近似します。正味勾配計算の詳細については、正味勾配計算の処理を参照してください。

  • より高いレベルの基本アルゴリズム (FFT アルゴリズムなど)

生成されたコードでのシフトの制御

いくつかのコンフィギュレーション パラメーターは、生成されたコードに表示されるシフトの数とスタイルに対して有効です。

  • Signed integer division rounds to

    このパラメーターを [負方向] または [ゼロ方向] に設定すると、余分な生成コードを回避できます。

  • 固定小数点の正味勾配計算に除算を使用

    このパラメーターを有効にすると、乗算とそれに続くシフトの代わりに除算を使用して固定小数点の正味勾配計算が実行されます。

  • Replace multiplications by powers of two with signed bitwise shifts (Embedded Coder)

    このパラメーターを有効にすると、2 のべき乗による乗算は符号付きのビット演算に置き換えられます。このオプションをオフにすると、MISRA C™ コンプライアンスがサポートされます。

  • Allow right shifts on signed integers (Embedded Coder)

    このパラメーターを有効にすると、生成されたコードには符号付き整数のビット単位の右シフトを含めることができます。符号付き整数でビット単位の右シフトを回避するには、このオプションをオフにします。

  • 算術シフトとして符号付き整数を右にシフト

    C コンパイラが符号付き整数の右シフトを算術右シフトとして実行する場合は、このパラメーターを選択します。