Ожидается ли, что слишком большое битовое смещение - неопределенное поведение в Rust?

Когда вы запускаете этот код:

#![allow(exceeding_bitshifts)]

fn main() {
    const NUMBER: u64 = 0b_10101010;

    fn print_shift(i: u32) {
        println!("{:b}", NUMBER >> i);
    }

    print_shift(65);
    println!("{:b}", NUMBER >> 65);
}

Вы видите, что смещение битов числа со значением, которое превышает длину в битах, приводит к другому поведению при выполнении во время компиляции или во время выполнения.

Это нормальное поведение? Это где-то задокументировано? Этого нет в списке задокументированных неопределенных действий.

1 ответ

Решение

Нет, это не ожидается, но это не неопределенное поведение. Это просто ошибка.

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


Когда речь идет о сборках отладки и выпуска, ожидается поведение "слишком больших" сдвигов битов, которое также не является неопределенным поведением. Подсказка в сообщении об ошибке:

попытка сдвига вправо с переполнением

Целочисленное переполнение не является ни небезопасным, ни неопределенным:

Компилятор Rust не считает следующие поведения небезопасными, хотя программист может (должен) счесть их нежелательными, неожиданными или ошибочными.

  • ...
  • Целочисленное переполнение

Смотрите также:

Другие вопросы по тегам