【问题标题】:How to get the next pointer?如何获得下一个指针?
【发布时间】:2017-05-01 19:32:52
【问题描述】:

我有一个用 C 实现的函数,我想用 Rust 编写一个具有相同接口的函数。该函数接收指向数组开头的指针 (win8_t *) 和数组的长度。我需要能够遍历数组。

必须有更好的方法来获取下一个值,但现在我可以做这个奇怪的事情:

use std::mem;
pub extern "C" fn print_next(i: *const u8) {
    let mut ii = unsafe { mem::transmute::<*const u8, i64>(i) };
    ii += 1;
    let iii = unsafe { mem::transmute::<i64, *const u8>(ii) };
    let jj = unsafe { *iii };
    println!("{}", jj); // jj is next value
}

【问题讨论】:

标签: rust raw-pointer


【解决方案1】:

正如 Shepmaster 所说,您可能需要提供切片的长度。

大多数时候你都在使用指针,你的函数是不安全的(因为你通常需要在某个时候取消引用它)。将它们标记为不安全以将安全责任委托给调用者可能是个好主意。

以下是一些使用offsetfrom_raw_slice 的示例:

use std::mem;
use std::slice;

// unsafe!
pub extern "C" fn print_next(i: *const u8) {
    let mut ii = unsafe { mem::transmute::<*const u8, i64>(i) };
    ii += 1;
    let iii = unsafe { mem::transmute::<i64, *const u8>(ii) };
    let jj = unsafe { *iii };
    println!("{}", jj); // jj is next value
}

// unsafe!
pub unsafe extern "C" fn print_next2(i: *const u8) {
    let j = *i.offset(1);
    println!("{}", j);
}

// (less but still ...) unsafe!
pub unsafe extern "C" fn print_next3(i: *const u8, len: usize) {
    let slice = slice::from_raw_parts(i, len);
    // we are not checking the size ... so it may panic!
    println!("{}", slice[1]);
}

fn main() {
    let a = [9u8, 4, 6, 7];
    print_next(&a as *const u8);
    unsafe {
        print_next2(&a[1] as *const u8);
        print_next3(&a[2] as *const u8, 2);
    }

    // what if I print something not in a??
    print_next(&a[3] as *const u8); // BAD
    unsafe { 
        print_next2(&a[3] as *const u8); // BAD
        print_next3(&a[3] as *const u8, 2); // as bad as others, length is wrong

        print_next3(&a[3] as *const u8, 1); // panic! out of bounds
    }
}

【讨论】:

  • print_next3 是我宣传的“正确”解决方案,尽管 OP 没有要求它。这是因为它将不安全性集中在一个地方:对slice::from_raw_parts 的调用。之后,Rust 将负责安全性,只要调用者没有对数据的位置和长度撒谎,一切都会是安全的。调用者建议的 API 受到 C 设计的影响,其中指针算法是自然而然的。在 Rust 中,您希望首先得到一个正确的检查切片,然后做其他所有事情。
  • 顺便说一句,我认为您不需要第二个 transmute 语句,因为您只需执行 as *const u8 即可将 i64 转换为原始指针。 play.rust-lang.org/…
猜你喜欢
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2022-11-23
  • 2017-05-26
  • 2010-10-17
  • 2018-12-02
相关资源
最近更新 更多