exponenta event banner

Недопустимые операции смены

Недопустимые операции смены

Описание

Эта проверка операций смены для переменной 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. Таким образом, проверка недопустимых операций смены приводит к появлению красной ошибки.

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

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

В этом примере левый операнд операции левого сдвига отрицателен.

Коррекция - опция Использовать анализ в пространстве (Use Polyspace analysis)

Можно использовать левую смену для отрицательных чисел и не создавать красную ошибку недопустимых операций смены. Чтобы разрешить такие левые сдвиги, на панели Конфигурация в разделе Проверить поведение выберите Разрешить отрицательный операнд для левых сдвигов.

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

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

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