Primitive Type fn
1.0.0 ·Expand description
函数指针,例如 fn(usize) -> bool
。
另请参见 traits Fn
,FnMut
和 FnOnce
。
函数指针是指向 code 的指针,而不是数据。它们可以像函数一样被调用。
像引用一样,函数指针被假定为不为空,所以如果您想通过 FFI 传递函数指针并能够容纳空指针,请使用所需的签名来创建类型 Option<fn()>
。
Safety
普通函数指针是通过强制转换不能捕获环境的普通函数或闭包而获得的:
fn add_one(x: usize) -> usize {
x + 1
}
let ptr: fn(usize) -> usize = add_one;
assert_eq!(ptr(5), 6);
let clos: fn(usize) -> usize = |x| x + 5;
assert_eq!(clos(5), 10);
Run除了根据其签名而有所不同外,函数指针还具有两种形式:安全和不安全。
普通 fn()
函数指针只能指向安全函数,而 unsafe fn()
函数指针可以指向安全或不安全函数。
fn add_one(x: usize) -> usize {
x + 1
}
unsafe fn add_one_unsafely(x: usize) -> usize {
x + 1
}
let safe_ptr: fn(usize) -> usize = add_one;
// ERROR: 不匹配的类型:预期正常 fn,发现不安全 fn let bad_ptr: fn(usize) -> usize=add_one_unsafely;
let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
RunABI
最重要的是,函数指针可以根据它们使用的 ABI 有所不同。这是通过在类型之前添加 extern
关键字,然后是所涉及的 ABI 来实现的。默认的 ABI 是 “Rust”,即 fn()
是与 extern "Rust" fn()
完全相同的类型。
指向带有 C ABI 的函数的指针的类型为 extern "C" fn()
。
extern "ABI" { ... }
块用 ABI “ABI” 声明函数。此处的默认值为 “C”,即,在 extern {...}
块中声明的函数具有 “C” ABI。
有关更多信息和受支持的 ABI 列表,请参见 nomicon 中关于外部调用约定的部分。
可变函数
“C” 或 “cdecl” ABI 的 Extern 函数声明也可以 variadic,允许使用可变数量的参数来调用它们。普通的 Rust 函数,即使是 extern "ABI"
的函数,也不能可变。
有关更多信息,请参见 关于可变参数函数的 nomicon 部分。
创建函数指针
如果 bar
是函数的名称,则表达式 bar
不是 函数指针。相反,它表示唯一标识函数 bar
的无法命名类型的值。该值的大小为零,因为该类型已经标识了该函数。
这样做的好处是 “calling” 值 (实现 Fn*
traits) 不需要动态分配。
零大小的类型 强制 到常规函数指针。例如:
use std::mem;
fn bar(x: i32) {}
let not_bar_ptr = bar; // `not_bar_ptr` 是零大小的,唯一标识是 `bar`
assert_eq!(mem::size_of_val(¬_bar_ptr), 0);
let bar_ptr: fn(i32) = not_bar_ptr; // 强制转换为函数指针
assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
let footgun = &bar; // 这是对标识 `bar` 的零大小类型的共享引用
Run最后一行显示 &bar
也不是函数指针。相反,它是特定于函数的 ZST 的引用。当 bar
是一个函数时,&bar
基本上不是您想要的。
转换为整数和从整数转换
您将函数指针直接转换为整数:
let fnptr: fn(i32) -> i32 = |x| x+2;
let fnptr_addr = fnptr as usize;
Run但是,直接回退是不可能的。您需要使用 transmute
:
let fnptr = fnptr_addr as *const ();
let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
assert_eq!(fnptr(40), 42);
Run至关重要的是,我们在转换为函数指针之前 as
-cast 为一个裸指针。
这避免了整数到指针 transmute
,这可能是有问题的。
在裸指针 (即两个指针类型) 之间转换是可以的。
请注意,所有这些都不能移植到函数指针和数据指针具有不同大小的平台。
trait 实现
在本文档中,简写 fn (T₁, T₂,…, Tₙ)
用于表示可变长度的非可变函数指针。请注意,这是一种方便的符号,以避免重复文档,不是有效的 Rust 语法。
由于 Rust 的类型系统中的临时限制,这些 traits 仅在 "Rust"
和 "C"
ABI 上使用不超过 12 个参数的函数上实现。在未来,这可能会改变:
以下 traits 是为具有任意数量参数和任意 ABI 的函数指针实现的。 这些 traits 具有由编译器自动生成的实现,因此不受缺少语言特性的限制:
此外,所有 safe 函数指针都实现了 Fn
、FnMut
和 FnOnce
,因为这些 traits 是编译器特别知道的。
Trait Implementations§
source§impl<Ret, T> Clone for fn (T₁, T₂, …, Tₙ) -> Ret
impl<Ret, T> Clone for fn (T₁, T₂, …, Tₙ) -> Ret
这个 trait 是在具有任意数量参数的函数指针上实现的。
impl<Ret, T> Copy for fn (T₁, T₂, …, Tₙ) -> Ret
这个 trait 是在具有任意数量参数的函数指针上实现的。
Auto Trait Implementations§
impl<Ret, T> RefUnwindSafe for fn (T₁, T₂, …, Tₙ) -> Ret
impl<Ret, T> Send for fn (T₁, T₂, …, Tₙ) -> Ret
impl<Ret, T> Sync for fn (T₁, T₂, …, Tₙ) -> Ret
impl<Ret, T> Unpin for fn (T₁, T₂, …, Tₙ) -> Ret
impl<Ret, T> UnwindSafe for fn (T₁, T₂, …, Tₙ) -> Ret
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<F> PartialOrd<F> for Fwhere
F: FnPtr,
impl<F> PartialOrd<F> for Fwhere F: FnPtr,
source§impl<'a, F> Pattern<'a> for Fwhere
F: FnMut(char) -> bool,
impl<'a, F> Pattern<'a> for Fwhere F: FnMut(char) -> bool,
§type Searcher = CharPredicateSearcher<'a, F>
type Searcher = CharPredicateSearcher<'a, F>
pattern
#27721)source§fn into_searcher(self, haystack: &'a str) -> CharPredicateSearcher<'a, F>
fn into_searcher(self, haystack: &'a str) -> CharPredicateSearcher<'a, F>
pattern
#27721)self
和 haystack
构造关联的搜索器以进行搜索。source§fn is_contained_in(self, haystack: &'a str) -> bool
fn is_contained_in(self, haystack: &'a str) -> bool
pattern
#27721)source§fn is_prefix_of(self, haystack: &'a str) -> bool
fn is_prefix_of(self, haystack: &'a str) -> bool
pattern
#27721)source§fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str>
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str>
pattern
#27721)source§fn is_suffix_of(self, haystack: &'a str) -> boolwhere
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
fn is_suffix_of(self, haystack: &'a str) -> boolwhere CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
pattern
#27721)source§fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>where
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>where CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
pattern
#27721)