Неожиданное целочисленное переполнение в выражении - PullRequest
3 голосов
/ 25 июня 2019

Я пытаюсь получить unsigned, который будет полностью заполнен (это будет 32 из них в двоичном представлении. Я пытался использовать это:

constexpr unsigned all_ones = (((1 << 31) - 1) << 1) | 1;

, но при компиляции (g ++ onUbuntu) выдает следующую ошибку:

error: overflow in constant expression [-fpermissive]

Что вызывает эту ошибку? Для меня выражение выглядит хорошо, как разобран здесь:

1       = 000...001
  << 31 = 100...000
  - 1   = 011...111
  << 1  = 111...110
  | 1   = 111...111

Я знаю, что могу получитьтребуемое значение другими способами (например, ~ 0u), но я спрашиваю, почему этот метод не работает.

Ответы [ 2 ]

6 голосов
/ 25 июня 2019

Ваше выражение использует целочисленные константы со знаком и переполняется в знаковый бит (что приводит вас к неопределенному поведению). Вы можете избежать ошибки, указав константу без знака:

constexpr unsigned all_ones = (((1U << 31) - 1) << 1) | 1;

Но выражение все еще слишком сложное и лучше выражается как:

constexpr unsigned all_ones = ~0U;
3 голосов
/ 25 июня 2019

Я бы попытался использовать определения в заголовках, это то, для чего они нужны, вы в основном запрашиваете наибольшее значение, которое вы можете представить для целого числа без знака.

constexpr без знака all_ones = UINT_MAX;

Смотрите здесь: http://www.cplusplus.com/reference/climits/

...