如何以字节为单位获取指针偏移?

时间:2016-10-28 17:40:42

标签: rust

虽然Rust中的原始指针具有offset方法,但这只会增加指针的大小。如何以字节为单位访问指针?

C中有这样的事情:

var_offset = (typeof(var))((char *)(var) + offset);

2 个答案:

答案 0 :(得分:8)

answer我链接到您之前的问题:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        unsafe { &(*(0 as *const $ty)).$field as *const _ as usize }
    }
}

fn main() {
    let p: *const Baz = 0x1248 as *const _;
    let p2: *const Foo = ((p as usize) - offset_of!(Foo, memberB)) as *const _;
    println!("{:p}", p2);
}

我们可以看到p2的计算可以将指针无痛转换为整数(此处为usize),在其上执行算术,然后将结果转换回指针

isizeusize是通用字节大小的指针类型:)

答案 1 :(得分:1)

感谢@Matthieu M.的回答,这可以使用指针偏移完成,这是一个可重用的宏:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
}

macro_rules! check_type_pair {
    ($a:expr, $b:expr) => {
        if false {
            let _type_check = if false {$a} else {$b};
        }
    }
}

macro_rules! parent_of_mut {
    ($child:expr, $ty:ty, $field:ident) => {
        {
            check_type_pair!(&(*(0 as *const $ty)).$field, &$child);
            let offset = offset_of!($ty, $field);
            &mut *(((($child as *mut _) as usize) - offset) as *mut $ty)
        }
    }
}

macro_rules! parent_of {
    ($child:expr, $ty:ty, $field:ident) => {
        {
            check_type_pair!(&(*(0 as *const $ty)).$field, &$child);
            let offset = offset_of!($ty, $field);
            &*(((($child as *const _) as usize) - offset) as *const $ty)
        }
    }
}

这样,当我们在struct中有一个字段时,我们可以得到这样的父结构:

fn some_method(&self) {
    // Where 'self' is ParentStruct.field,
    // access ParentStruct instance.
    let parent = unsafe { parent_of!(self, ParentStruct, field) };
}

check_type_pair有助于避免selfParentStruct.field类型不同的简单错误。但是,当结构中的两个不同成员具有相同类型时,它并非万无一失。