メインコンテンツ

無効なシフト演算

説明

変数 var でのシフト演算に対するこのチェックでは、以下を判別します。

  • シフト量が var の型に応じて許可される範囲より大きいかどうか。

  • シフトが左シフトの場合は、var が負かどうか。

すべて展開する

#include <stdlib.h>
#define shiftAmount 32
enum shiftType {
 SIGNED_LEFT,
 SIGNED_RIGHT,
 UNSIGNED_LEFT,
 UNSIGNED_RIGHT
};

enum shiftType getShiftType();

void main() {
  enum shiftType myShiftType = getShiftType();
  int signedInteger = 1;
  unsigned int unsignedInteger = 1;
  switch(myShiftType) {
  case SIGNED_LEFT: 
    signedInteger = signedInteger << shiftAmount;
    break;
  case SIGNED_RIGHT: 
    signedInteger = signedInteger >> shiftAmount;
    break;
  case UNSIGNED_LEFT: 
    unsignedInteger = unsignedInteger << shiftAmount;
    break;
  case UNSIGNED_RIGHT: 
    unsignedInteger = unsignedInteger >> shiftAmount;
    break;
  }
}

この例では、シフト量 shiftAmount が、符号付きおよび符号なしの int に対し許可される範囲を外れています。したがって、[無効なシフト演算] チェックはレッド エラーを生成します。

修正 — シフト量を範囲内に維持

1 つの修正方法として、符号なしの整数では範囲 0..31、符号付き整数では範囲 0...30 内に収まるようシフト量を維持するとします。この修正が奏功するのは、ターゲット プロセッサにおいて int のサイズが 32 の場合です。

#include <stdlib.h>
#define shiftAmountSigned 30
#define shiftAmount 31
enum shiftType {
 SIGNED_LEFT,
 SIGNED_RIGHT,
 UNSIGNED_LEFT,
 UNSIGNED_RIGHT
};

enum shiftType getShiftType();

void main() {
  enum shiftType myShiftType = getShiftType();
  int signedInteger = 1;
  unsigned int unsignedInteger = 1;
  switch(myShiftType) {
  case SIGNED_LEFT: 
    signedInteger = signedInteger << shiftAmountSigned;
  
    break;
  case SIGNED_RIGHT: 
    signedInteger = signedInteger >> shiftAmountSigned;
  
    break;
  case UNSIGNED_LEFT: 
    unsignedInteger = unsignedInteger << shiftAmount;
  
     break;
  case UNSIGNED_RIGHT: 
    unsignedInteger = unsignedInteger >> shiftAmount;
  
    break;
  }
}
void main(void) {
  int x = -200;
  int y;
  y = x << 1; 
}

この例では、左シフト演算の左のオペランドが負数です。

修正 — Polyspace 解析オプションを使用

負の数値に対して左シフトを使用し、かつ [無効なシフト演算] のレッドエラーが生成されないようにできます。そのような左シフトを可能にするには、[構成] ペインの [チェック動作] で、[左シフトで負のオペランドを許可] を選択します。

void main(void) {
  int x = -200;
  int y;
  y = x << 1; 
}
short getVal();

int foo(void) {
  long lvar;
  short svar1, svar2;

  lvar = 0;
  svar1 = getVal();
  svar2 = getVal();

  lvar =  (svar1 - svar2) << 10;
  if (svar1 < svar2)  {
    return 1;
  } else {
    return 0;
  }
}

int main(void) {
  return foo();
}

この例では、svar1 < svar2 の場合、<< の左のオペランドは負である可能性があります。したがって、<<[シフト演算] チェックはオレンジになります。オレンジ チェックの後、エラーを含む実行パスは打ち切られます。そのため、[無効なシフト演算] オレンジ チェックに従い、Polyspace®svar1 >= svar2 と仮定します。ステートメント if(svar1 < svar2) の分岐は到達不能になります。

チェック情報

グループ: 数値
言語: C | C++
頭字語: SHF