Invalid shift operations

Операции сдвига недопустимы

Описание

Эта проверка операций сдвига переменной 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. Поэтому проверка Invalid shift operations приводит к красной ошибке.

Коррекция - Сохраните величину сдвига в границах

Одним из возможных коррекций является сохранение величины сдвига в область значений 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

Можно использовать левые сдвиги для отрицательных чисел и не создавать ошибку красного Invalid shift operations. Чтобы разрешить такие левые сдвиги, на панели Configuration, под Check Behavior, выберите Allow negative operand for left shifts.

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, левый операнд << может быть отрицательным. Поэтому Shift operations проверяйте << оранжевый. После оранжевой проверки пути выполнения, содержащие ошибку, обрезаются. Поэтому, следуя оранжевой проверке Invalid shift operations, Polyspace® принимает, что svar1 >= svar2. Ветвь оператора, if(svar1 < svar2), недоступен.

Проверяйте информацию

Группа: Численный
Язык: C | C++
Акроним: SHF