在Rust中,一个过大的位移操作是否属于未定义行为?

7
当您运行此代码时:
#![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个回答

6
不,这并不是预期结果,但它也不是未定义行为。这只是一个“错误”
在编译时计算常量和在运行时计算值之间不应该有任何区别。总的来说,这是一个难题,因为编译代码的机器和运行代码的机器可能具有完全不同的架构。
当谈到调试和发布版本时,“过大”的位移行为是预期的,也不是未定义的行为。线索在于错误信息:

尝试进行溢出右移

整数溢出既不是不安全的也不是未定义的

Rust编译器不认为以下行为是不安全的,但程序员可能(应该)认为它们是不希望、意外或错误的。

  • ...
  • 整数溢出
另请参阅:

同样的函数和参数(x.shr(y))在不同的调用中给出不同的答案。这不是未定义行为吗? - Boiethios
2
@Boiethios 我不确定你是否正确使用了“未定义行为”这个术语。random()(通常)在不同的调用中返回不同的答案,但这并不意味着它的行为是未定义的。 - Shepmaster
不,UB特指规范未定义行为的情况,现代C/C++编译器越来越将其视为优化机会,导致当某人遇到C/C++中许多未定义行为的情况时,结果变得越来越令人困惑。 - plugwash
另一方面,Rust非常努力地避免未定义的行为,在无法避免的情况下(某些指针相关操作本质上是不安全的),要求程序员通过“unsafe”块明确地承认这一点。 - plugwash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接