UB со сдвигами беззнаковых переменных

Рейтинг: 1Ответов: 1Опубликовано: 27.04.2023

Код следующий:

#include <iostream>

int main ()
{
  unsigned int a = 1;
  unsigned int b = 5;
  unsigned int c = (a << (a << b)) << b;
  std::cout << "s  : c \t\t= " << c << std::endl;;
  unsigned int x = 32u;
  std::cout << "s  : 1u<<x \t= " << (1u << x) << std::endl;

  return 0;
}

Компилирую в mingw (аналог gcc в винде). Под линуксом также пробовал через gcc - результат такой же. В зависимости от уровня оптимизации разный результат:

-O0:

s  : c          = 32
s  : 1u<<x      = 1

-O2:

s  : c          = 0
s  : 1u<<x      = 0

В коде по-видимому есть UB, но найти я его не могу, кажется, что там идут сдвиги беззнаковых переменных, а они UB не являются, и по логике оба ответа должны быть нулями.

Цитата с cppreference:

For unsigned a, the value of a << b is the value of a * 2^b , reduced modulo 2^N where N is the number of bits in the return type (that is, bitwise left shift is performed and the bits that get shifted out of the destination type are discarded).

Что тут не так?

Ответы

▲ 3Принят

Это UB согласно стандарту (7.6.7 Shift operators):

The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.