You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何获取字节数组非起始位置的&[u8]切片引用

Rust 缓冲区偏移拷贝实现方案

Rust 原生支持等价于C指针算术的安全操作,不需要依赖unsafe裸指针,这类缓冲区提取拷贝的需求有非常成熟的标准写法。

对应C指针算术的安全实现

你要传入源缓冲区指定偏移位置的片段,直接用Rust切片的范围索引即可。切片本身是带长度信息的胖指针,&buf[offset..offset+len]的效果和C里指针偏移offset个字节完全等价,而且会自动做边界检查,越界时会直接抛出错误,不会出现C语言里非法访问内存的问题。

比如你要从大缓冲区头部取两个16字节的值,调用你写的memcpy_safe时直接传对应范围的切片就行:

// 假设large_buf是你存储原始数据的大型缓冲区
let mut small_buf1 = [0u8; 16];
let mut small_buf2 = [0u8; 16];

// 取前16字节,等价于C里直接传large_buf的起始指针
memcpy_safe(&mut small_buf1, &large_buf[0..16]);
// 取偏移16字节开始的16字节,等价于C里传large_buf + 16的指针
memcpy_safe(&mut small_buf2, &large_buf[16..32]);

如果你的输入来源不可信(比如网络报文、用户输入),担心长度不足导致panic,可以用切片的get方法返回Option,自己处理长度不够的分支:

if let Some(src_part) = large_buf.get(16..32) {
    memcpy_safe(&mut small_buf2, src_part);
} else {
    // 处理源缓冲区长度不足的错误
}

这类拷贝需求的标准写法

你自己手写的memcpy_safe逐字节循环其实没必要,Rust标准库已经提供了经过充分优化的拷贝方法:

  • 如果要求源和目标长度完全一致,直接用切片自带的copy_from_slice即可,性能和C标准库的memcpy持平,长度不匹配时会直接panic,避免截断导致的隐蔽bug:
    // 直接替换自定义的memcpy_safe即可,不需要额外封装
    small_buf1.copy_from_slice(&large_buf[0..16]);
    small_buf2.copy_from_slice(&large_buf[16..32]);
    
  • 如果你确实需要长度不匹配时自动截断的逻辑,也不用手写逐字节循环,复用标准库方法即可,比手写循环可靠性更高:
    fn memcpy_safe(dest: &mut [u8], src: &[u8]) {
        let copy_len = dest.len().min(src.len());
        if copy_len != dest.len() || copy_len != src.len() {
            println!("memcpy_safe found src and dest do not have the same length, truncating to {} bytes (src: {}, dest: {})", copy_len, src.len(), dest.len());
        }
        dest[..copy_len].copy_from_slice(&src[..copy_len]);
    }
    

额外注意事项

  • 日常业务代码优先用安全切片操作,不要为了省一丢丢边界检查的开销就用unsafe裸指针做偏移,release模式下边界检查的开销极低,绝大多数场景根本感知不到
  • 固定长度的小缓冲区优先用数组类型(比如[u8;16])而不是切片,配合copy_from_slice时编译器可以直接验证长度匹配,很多时候连运行时检查都能优化掉
  • 如果需要频繁做缓冲区的读写偏移操作,可以用std::io::Cursor,比自己手动维护偏移量更不容易出错

内容的提问来源于stack exchange,提问作者Dyskord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:18:41