跳转到内容

地址(Address)

address 是 Move 语言的内置类型,用于表示全局存储中的位置(有时称为账户).一个 address 值是一个 256 位(32 字节)的标识符.在给定地址下可以存储两种内容:模块资源.

虽然 address 底层实现是 256 位整数,但 Move 地址被设计为不透明的——它们不能从整数创建,不支持算术运算,也不可修改.尽管某些场景可能需要这类特性(例如 C 语言中的指针算术就有类似用途),但 Move 出于支持静态验证的设计目标,不允许这种动态行为.

你可以在运行时使用地址值(address 类型)来访问该地址下的资源,但_无法_通过地址值在运行时访问模块.

地址有两种形式:命名地址和数值地址.命名地址的语法遵循 Move 中命名标识符的通用规则.数值地址的语法不限于十六进制值,任何有效的 u256 数值都可以作为地址值,例如 42,0xCAFE2021 都是有效的数值地址字面量.

为区分地址是否在表达式上下文中使用,其语法会根据使用场景有所不同:

  • 当地址在表达式中使用时,必须以 @ 字符作为前缀,即 @<数值>@<命名地址标识符>
  • 在非表达式上下文中,地址可以不带 @ 前缀书写,即 <数值><命名地址标识符>

通常可以将 @ 视为一个运算符,它将地址从命名空间项转换为表达式项.

命名地址允许在任何使用地址的地方用标识符替代数值,而不仅限于值层面.命名地址在 Move 包中作为顶层元素(模块和脚本之外)声明和绑定,或作为参数传递给 Move 编译器.

命名地址仅存在于源代码层面,在字节码层面会被完全替换为其对应的数值.因此,模块和模块成员_必须_通过模块的命名地址访问,而不能通过编译时分配给命名地址的数值访问.例如,即使 Move 程序编译时将 my_addr 设为 0x2,use my_addr::foo 也_不等同_于 use 0x2::foo.这个区别在模块与脚本章节有更详细的讨论.

script {
fun example() {
let a1: address = @0x1; // 0x0000000000000000000000000000000000000000000000000000000000000001 的简写
let a2: address = @0x42; // 0x0000000000000000000000000000000000000000000000000000000000000042 的简写
let a3: address = @0xDEADBEEF; // 0x00000000000000000000000000000000000000000000000000000000DEADBEEF 的简写
let a4: address = @0x000000000000000000000000000000000000000000000000000000000000000A;
let a5: address = @std; // 将命名地址 `std` 的值赋给 `a5`
let a6: address = @66;
let a7: address = @0x42;
}
}
module 66::some_module { // 非表达式上下文,无需 @ 前缀
use 0x1::other_module; // 非表达式上下文,无需 @ 前缀
use std::vector; // 引用其他模块时可将命名地址作为命名空间项使用
...
}
module std::other_module { // 声明模块时可将命名地址作为命名空间项使用
...
}

address 值的主要用途是与全局存储操作进行交互.

address 值会与 exists,borrow_global,borrow_global_mutmove_from 操作 一起使用.

唯一 使用 address 的全局存储操作是 move_to,该操作使用 signer.

与语言中内置的其他标量值一样,address 值是隐式可复制的,这意味着它们无需显式指令(如 copy)即可被复制.