【问题标题】:Literal out of range warning when iterating over all values of u8 [duplicate]迭代u8的所有值时出现文字超出范围警告[重复]
【发布时间】:2016-11-04 11:15:27
【问题描述】:

据我所知,for-loop 中的范围包括下限和上限。这在以下代码中引入了一个问题:

fn main() {
    let a: u8 = 4;

    for num in 0..256 {
        if num == a {
            println!("match found");
            break;
        }
    }
}

我想从 0 到 255 循环 256 次,这符合u8 支持的数据范围。但是由于范围是不包括上限的,所以我必须将 256 作为进程 255 的限制。因此,编译器会发出以下警告。

warning: literal out of range for u8
 --> src/main.rs:4:19
  |
4 |     for num in 0..256 {
  |                   ^^^
  |
  = note: #[warn(overflowing_literals)] on by default

当我执行这个时,程序会跳过for 循环。

在我看来,编译器必须忽略范围中的 256 并接受该范围为u8 范围。这是正确的吗?有没有其他方法可以给出范围?

【问题讨论】:

    标签: rust


    【解决方案1】:

    正如 alex 已经说过的,最好使用更大的整数类型(如 u32)进行迭代并在与您正在搜索的 u8 进行比较时将其强制转换:

    let a: u8 = 4;
    
    for num in 0..256 {
        if (num as u8) == a {
            println!("match found");
            break;
        }
    }
    

    在这种特殊情况下,您也可以使用a half-open range

    let a: u8 = 4;
    
    for num in 0.. {
        if num == a {
            println!("match found");
            break;
        }
    }
    

    当我执行这个时,程序会跳过 for 循环。

    256 的二进制表示是1_0000_0000u8 只保存最右边的 8 位,所以只保存 0s。因此0..256u8 等价于0..0,当然是一个空范围。

    【讨论】:

    • 半开范围是我需要的。但是如果没有中断,它会创建一个无限循环,所以需要小心。 Rust 文档中缺少半开范围?
    • @Steve:它被称为RangeFrom。还有RangeToRangeFull
    • 使用半开范围的想法很有趣,我想知道它是否消除了对包含范围的部分需求。
    • 我仍然认为语言中应该有一种方法可以在不使用类型转换的情况下表达完整的 u8 范围。
    • @Steve 我想很多人都同意。但这已经在社区中引发了一场巨大的争论,通常是关于语法的。最好不要在 cmets 中开始新的讨论:P
    【解决方案2】:

    您可以组合迭代器来创建完整的u8 范围:

    use std::iter::once;
    for i in (0..255).chain(once(255)){
        //...
    }
    

    在夜间 Rust 中,您可以使用 inclusive range:

    #![feature(inclusive_range_syntax)]
    for i in 0...255 {
        //...
    }
    

    【讨论】:

      【解决方案3】:

      我认为您正在比较不同的类型,因此需要进行转换。试试这个:

      for num in 0..256 {
          let y = num as u8;
          if y == a {
              println!("found");
              break;
          }
      }
      

      【讨论】:

      • 这不完全是这里的问题。事实上,0..256 范围被推断为具有与 a 相同类型的元素,这首先导致了编译警告。
      • @E_net4 实际上,它可以工作(我至少测试了我的铸造版本)。显然,as-cast 不是编译器推断类型的有效提示。所以在这个例子中,它可能是Range<i32>
      • @LukasKalbertodt 我没有说这个解决方案不起作用。问题在于暴露的原因,那就是……嗯,容易产生歧义。
      • 所以在这种情况下使用as 不合适? Lucas 你说这不是编译器的有效提示,你能解释一下原因吗?
      • @alex 实际发生的是num as u8 告诉编译器需要从范围的元素类型转换为u8,并“削减”没有它会发生的类型推断。与其假设numa 具有相同类型,因此推断范围为Range<u8>,它只是“回退”到Range<i32>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 2015-03-13
      相关资源
      最近更新 更多