< 返回版块

leslieDD 发表于 2021-05-18 10:54

#[derive(Debug)]
struct DianDian {
    a: i32,
    b: i32,
    c: u32,
}

fn main() {
    let a = DianDian { a: 1, b: 2, c: 3 };
    let val = std::ptr::addr_of!(a);
    let b = move || {
        let val2 = std::ptr::addr_of!(a);
        println!("addr of a is {:?}, b is {:?}", val2, val);
        let v1 = val as u128;
        let v2 = val2 as u128;
        println!("val sub val2 is {}", v1 - v2);
        let mut c = a;
        c.a += 1;
        println!("c is {:?}", c);
    };
    b();
}

输出结果是:

PS D:\rust\yb> cargo run
   Compiling yb v0.1.0 (D:\rust\yb)
    Finished dev [unoptimized + debuginfo] target(s) in 1.05s
     Running `target\debug\yb.exe`
addr of a is 0xe7012ff800, b is 0xe7012ff7d0
thread 'main' panicked at 'attempt to subtract with overflow', src\f3\pin3.rs:16:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\yb.exe` (exit code: 101)

如果想知道,两个地址值之间的差值是多少,要怎么做呢

评论区

写评论
Aya0wind 2021-05-18 15:20

offset_from是unsafe因为有的条件无法在语言层面保证,比如两个指针不是指向同一个序列,或者结果导致isize溢出等等。但是转成usize去相减也没有保证这些条件吧,实际上还是unsafe的,只不过你强行让他变成safe了而已,这样也不太合适。

--
👇
Neutron3529: pub const unsafe fn offset_from(self, origin: *const T) -> isize

大概因为这是unsafe……

--
👇
Aya0wind: 为什么不用offset_from函数?

Neutron3529 2021-05-18 14:12

pub const unsafe fn offset_from(self, origin: *const T) -> isize

大概因为这是unsafe……

--
👇
Aya0wind: 为什么不用offset_from函数?

Aya0wind 2021-05-18 13:36

为什么不用offset_from函数?

viruscamp 2021-05-18 13:19

指针和usize 是无损转换的, usize 目前只有 64bit 和 32bit,两个 u64 相加相减确实可能超 u64,但不可能超 i128 的。 你看看 u64 最大是多少 0xffffffffffffffff 16个f,这个放不下 0x7ffee66c3ef8 吗?那 i128 肯定也够的。

👇
qingmo: 感觉i128本身也承载不了这个数据吧? 理论上来说0x7ffee66c3ef8应该是140732764274424 我能想到的就是使用nums中的BigInt,但是这里的val又是*const DianDian,不知道该如何将它转化为一个BigInt? 也许是 BigInt(val * 0xffff) + BigInt(val>>16 * 0xffff)*0xffff + + BigInt(val>>16 * 0xffff)*0xffffffff 这么个思路。求指导

Neutron3529 2021-05-18 13:10

其实这里直接开--release就好

(BTW,用debug模式,不写wrapping_sub是什么习惯?)

(wrapping_sub放在这里很合适,只要不打印,没人关心isize跟usize之间有什么区别)

Bai-Jinlin 2021-05-18 12:17
fn distance<T>(l: *const T, r: *const T) -> isize {
    (l as isize - r as isize) / core::mem::size_of::<T>() as isize
}
fn main() {
    let a = [1, 2, 3];
    println!("{}", distance(&a[2] as *const i32, &a[0] as *const i32,));
}
qingmo 2021-05-18 12:01

经过一个大哥指导,这里应该用isize或者usize 128肯定是不够的。

--
👇
qingmo: 感觉i128本身也承载不了这个数据吧? 理论上来说0x7ffee66c3ef8应该是140732764274424 我能想到的就是使用nums中的BigInt,但是这里的val又是*const DianDian,不知道该如何将它转化为一个BigInt? 也许是 BigInt(val * 0xffff) + BigInt(val>>16 * 0xffff)*0xffff + + BigInt(val>>16 * 0xffff)*0xffffffff 这么个思路。求指导

qingmo 2021-05-18 11:57

感觉i128本身也承载不了这个数据吧? 理论上来说0x7ffee66c3ef8应该是140732764274424 我能想到的就是使用nums中的BigInt,但是这里的val又是*const DianDian,不知道该如何将它转化为一个BigInt? 也许是 BigInt(val * 0xffff) + BigInt(val>>16 * 0xffff)*0xffff + + BigInt(val>>16 * 0xffff)*0xffffffff 这么个思路。求指导

作者 leslieDD 2021-05-18 11:28

明白了,两个值,可能减出负数来,负数并不是u8类型的合法值

--
👇
viruscamp: ```rust let x = 3u8 - 4u8; // 有错吗? x 的类型是什么?值是什么?

所以,最简单改法是
```rust
        let v1 = val as i128;
        let v2 = val2 as i128;
viruscamp 2021-05-18 11:20
let x = 3u8 - 4u8; // 有错吗? x 的类型是什么?值是什么?

所以,最简单改法是

        let v1 = val as i128;
        let v2 = val2 as i128;
1 共 10 条评论, 1 页