Rust中令人困惑的全局常量变量

mitkmikd  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(99)

我做了很多我不能理解的rust全局变量的实验;为什么会这样

#![allow(unused)]

const I:i32 = 10;

fn main() {
    let gi = I;
    println!("{}", gi);
    const I:i32 = 20;
    println!("{}", gi);
}

当我这样做时,我期望输出

10
10

但我得到的输出是这样的

20
20

我没有碰gi,但它仍然改变,当我改变全局变量I,如果我改变I后,打印gi一次,我不明白为什么第一个输出也改变,打破了控制流

0md85ypi

0md85ypi1#

这不是重新分配一个应该是const的东西的问题,而是用另一个同名的常量来隐藏一个常量的问题。
第一个常量具有全局作用域,但第二个常量存在于main()函数的作用域中。在这个函数中,如果我们引用I,它将在较小的封闭作用域中找到,即main()函数。
在下面的修改示例中,我引入了一个新的块来说明这一点。从gi的Angular 来看,I是在全局范围内找到的,但是一旦进入人工块I就引用了它的第二个定义(在这个块中)。
令人困惑的部分是,即使内部常量是在引用它的语句之后定义的,也会找到它。如果它是一个变量,它就不正确,但因为它是一个常数,顺序并不重要(这就像一个词汇替换)。如果顶部的I出现在main()函数的下面,情况也是一样的:它将存在于全局范围内。

const I: i32 = 10;

fn main() {
    let gi = I;
    println!("before block: gi={}  I={}", gi, I);
    {
        println!("enter block: gi={}  I={}", gi, I);
        const I: i32 = 20;
        println!("leave block: gi={}  I={}", gi, I);
    }
    println!("after block: gi={}  I={}", gi, I);
}
/*
before block: gi=10  I=10
enter block: gi=10  I=20
leave block: gi=10  I=20
after block: gi=10  I=10
*/
41ik7eoe

41ik7eoe2#

注意,I不是全局变量,而是一个常量,这是不一样的。常数不能更新,因为它们在编译时计算。
此外,Rust有关于阴影的词汇规则。本地名称将始终覆盖非本地名称。您在这里使用了#![allow(unused)],这让我认为您可能已经看到了以下警告,但没有注意它,而是选择忽略它:

warning: constant `I` is never used
 --> src/main.rs:1:7
  |
1 | const I:i32 = 10;
  |       ^
  |

这是相当明确的,虽然指出,你从来没有真正使用外部的I在您的代码,但内部的。
最后,对于常量和函数,声明的顺序并不重要,所以在函数体的中间声明常量与在顶部声明常量是一样的。
根据前面的解释,可以推断您的示例等效于:

const Outer_I:i32 = 10;

fn main() {
    const Local_I:i32 = 20;        

    let gi = Local_I;
    println!("{}", gi);
    println!("{}", gi);
}

相关问题