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

标签 pointers rust byte offset

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

在 C 中是这样的:

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

最佳答案

TL;DR:根据 RFC-2582,此答案调用未定义行为.

In particular, references must be aligned and dereferencable, even when they are created and never used.

还有一些讨论认为,字段访问本身会施加额外的要求,而提议的 &raw 并未解决这些要求。 , 由于使用 getelementptr inbounds , 请参阅 offsetof RFC 底部的问题


来自answer我链接到你之前的问题:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        //  Undefined Behavior: dereferences a null pointer.
        //  Undefined Behavior: accesses field outside of valid memory area.
        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是通用字节大小的指针类型:)


RFC-2582要被接受,这个 offset_of! 的实现是我最好的镜头:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        unsafe {
            //  Create correctly sized storage.
            //
            //  Note: `let zeroed: $ty = ::std::mem::zeroed();` is incorrect,
            //        a zero pattern is not always a valid value.
            let buffer = ::std::mem::MaybeUninit::<$ty>::uninit();

            //  Create a Raw reference to the storage:
            //  - Alignment does not matter, though is correct here.
            //  - It safely refers to uninitialized storage.
            //
            //  Note: using `&raw const *(&buffer as *const _ as *const $ty)`
            //        is incorrect, it creates a temporary non-raw reference.
            let uninit: &raw const $ty = ::std::mem::transmute(&buffer);

            //  Create a Raw reference to the field:
            //  - Alignment does not matter, though is correct here.
            //  - It points within the memory area.
            //  - It safely refers to uninitialized storage.
            let field = &raw const uninit.$field;

            //  Compute the difference between pointers.
            (field as *const _ as usize) - (uninit as *const_ as usize)
        }
    }
}

我对每一步都做了评论,说明了我认为它们合理的原因,以及为什么有些替代方案不合理——我在不安全代码中大力鼓励这样做——希望没有遗漏任何内容。

关于pointers - 如何以字节为单位获取指针偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40310483/

相关文章:

java - 如何在 Swift 中编写 Java 字节数组

rust - 在采用 &self 或 &mut self 的函数中进行模式匹配时,如何避免 ref 关键字?

java - SWIG - 为具有四个传递字节数组的参数的函数创建类型映射

c++ - 如何在使用 CryptoPP 解密流后执行 unpadding

c - 试图理解c中NULL的内存泄漏

rust - 使用在另一个文件中定义的未声明类型

rust - 如何编写将代码注入(inject)函数的自定义属性

c - 指向 char 数组的指针数组

c - C语言函数返回多个值的方法

C 函数指针类型兼容性