【问题标题】:Is there a differencee between str::as_bytes and CString::as_bytes_with_nul?str::as_bytes 和 CString::as_bytes_with_nul 之间有区别吗?
【发布时间】:2019-02-09 17:53:18
【问题描述】:

这样做有什么区别:

name.as_bytes()

还有这个:

CString::new(name)?.as_bytes_with_nul()

我想从name(即String)获取字节,以便我可以轻松地通过网络发送它们,我不确定这里是否需要CString

【问题讨论】:

    标签: string rust


    【解决方案1】:

    as_bytes_with_nul 的文档以:

    等效于as_bytes 函数,只是返回的切片包含尾随 nul 终止符。

    as_bytes 是:

    返回的切片包含尾随 nul 终止符

    (强调原文)

    是否需要传输 nul 字节取决于您,这取决于您如何通过网络发送数据(TCP/UDP?通过 TCP 的原始二进制数据?如果是,您打算如何分隔消息? JSON?等)。

    【讨论】:

    • 我应该更仔细地查看文档...谢谢您的宝贵时间
    【解决方案2】:

    只要您的字符串中没有0 UTF-8 代码单元,name.as_bytes()CString::new(name)?.as_bytes() 应该给您完全相同的字节。此外,CString.as_bytes_with_null() 将简单地附加一个0 字节。这是一个带有相当复杂的 UTF-8 字符串的小演示:

    use std::ffi::CString;
    
    fn main() {
        let message: String = "\nßщ\u{1F601}".to_string();
        println!("bytes_1: {:?}", message.as_bytes());
        println!("bytes_2: {:?}", CString::new(message.clone()).unwrap().as_bytes());
        println!("bytes_3: {:?}", CString::new(message.clone()).unwrap().as_bytes_with_nul());
    }
    

    结果符合预期(您可能会认出10,它对应于ASCII字符\n,在UTF-8中以相同的方式编码):

    bytes_1: [10, 195, 159, 209, 137, 240, 159, 152, 129]
    bytes_2: [10, 195, 159, 209, 137, 240, 159, 152, 129]
    bytes_3: [10, 195, 159, 209, 137, 240, 159, 152, 129, 0]
    

    如果您的字符串包含U+0000which is a valid Unicode code point,由UTF-8 中的单个0 字节编码,并且可能出现在普通字符串中,则会出现问题。例如:

    use std::ffi::CString;
    
    fn main() {
        let message: String = "\n\u{0000}\n\u{0000}".to_string();
        println!("bytes_1: {:?}", message.as_bytes());
        println!(
            "bytes_2: {:?}",
            match CString::new(message.clone()) {
                Err(e) => format!("an error: {:?}, as expected", e),
                Ok(_) => panic!("won't happen. .as_bytes() must fail."),
            }
        );
    }
    

    会给你

    bytes_1: [10, 0, 10, 0]
    bytes_2: "an error: NulError(1, [10, 0, 10, 0]), as expected"
    

    所以,简单的.as_bytes() 成功,但CString-version 失败。如果可能的话,我建议坚持使用name.as_bytes() 和 UTF-8,没有理由先将其转换为 CString。

    【讨论】:

      猜你喜欢
      • 2012-01-12
      • 2019-04-27
      • 2019-10-17
      • 2021-12-08
      • 2016-10-07
      • 2012-02-16
      • 2010-09-27
      • 2020-01-11
      • 2016-12-02
      相关资源
      最近更新 更多