一文解决Rust字符串:String,str,String,str,CString,CStr

news/2024/4/25 18:51:47/文章来源:https://blog.csdn.net/phthon1997/article/details/129139740

一、str和&str和String的区别

1.存放位置,可变不可变:

str来源于Rust本身的数据类型,而String类型来自于标准库。首先看一下str 和 String之间的区别:String是一个可变的、堆上分配的UTF-8的字节缓冲区。而str是一个不可变的固定长度的字符串,如果是从String解引用而来的,则指向堆上,如果是字面值,则指向静态内存。

2.来看一个比较奇怪的例子
let s:&str="abcd";
char *s="abcd";

在C语言中,s是一个指针类型,指向一个字符串,但是它不知道长度,操作不安全。
在Rust中,s的类型是&str,而“abcd”是str类型,这里的“abcd”就是字符串字面值,存放在Stack上的。s 是切片,切片是一个结构体,包含两个字段,一个是指向数据的指针,另一个是数据的长度。因此,我们有可能采用必要的措施,安全的使用变量 s,这就是比C语言更安全的地方。

3.String
#[derive(PartialOrd, Eq, Ord)]
pub struct String {vec: Vec<u8>,
}

切片 &str 虽然可以安全使用,但是,我们很难动态修改其内容 —— 其地址、长度都是固定的。于是 Rust 提供了数据类型 String。String 包含了数据指针、数组容量、数据长度等三个字段。如果新修改的数据长度在其容量范围内,数据可以原地修改。如果新修改的数据长度超出了容量范围,它可以重新申请更大的内存。于是我们看到,String 和 &str 是两个完全不一样的结构体。为什么字符串要保留这两种形式?原因就是效率。Rust 希望在数组容量不会变化的时候,用 &str。在数组长度可能发生变化的情况下,使用 String。
补充几点关于String的:String 总是 “有效的” UTF-8,Rust字符串只能是UTF-8的类型。另外,不能用索引访问 String,因为有些字符的编码可能是多个字节,取到中间就是没有意义的。

4.&str或str转String
let s: String = "hello".to_string();
let t: String = String::from("hello");
5.String转&str或str

在 Rust 中,凡是需要用 &str 的地方,都可以直接用 &String 类型的数据。&String和&str其实也是差不多的。

fn greet(s: &str) {...
}
fn main() {let s: String = String::from("hello");greet(&s);
}

那么如何选择使用&str还是String呢?
规则很简单,一般情况下,&str 用于只读数据,String 用于可修改的数据。

二、CString和CStr或&CStr

1.CString和CStr

对于C语言来说,字符串有两种,一种是共享的只读字符串 char * ,不能修改。另一种是动态分配的可变字符串 char [],可以修改。
而在Rust里面,字符串是由字符的 UTF-8 编码组成的字节序列。表示的类型有很多种。
字符串则比较复杂,Rust 中的字符串,是一组u8组成的 UTF-8 编码的字节序列,字符串内部允许NULL字节;但在 C 中,字符串只是指向一个char的指针,用一个NULL字节作为终止。
我们需要做一些特殊的转换,在 Rust FFI 中使用std::ffi::CStr,它表示一个NULL字节作为终止的字节数组,可以通过 UTF-8 验证转换成 Rust 中的&str。
CStr:表示以空字符终止的 C 字符串或字节数组的借用,属于引用类型。一般用于和 C 语言交互,由 C 分配并被 Rust 借用的字符串。
CString:表示拥有所有权的,中间没有空字节,以空字符终止的字符串类型。一般用于和 C 语言交互时,由 Rust 分配并传递给 C 的字符串。
下面这段代码,在这里get_string使用CStr::from_ptr从C的char*获取一个字符串,并且转化成了一个String。

fn get_string() -> String {
unsafe {
let raw_string: *mut c_char = char_func();
let cstr = CStr::from_ptr(raw_string);
cstr.to_string_lossy().into_owned()
}
}

和CStr表示从C中来,rust不拥有归属权的字符串相反,CString表示由rust分配,Rust拥有所有权,可以进行修改,用以传给C程序的字符串。

use std::ffi::CString;
use std::os::raw::c_char;
extern {
fn my_printer(s: *const c_char);
}let c_to_print = CString::new("Hello, world!").unwrap();
unsafe {
my_printer(c_to_print.as_ptr()); // 使用 as_ptr 将CString转化成char指针传给c函数
}
2.CString 是一种类型,表示一个拥有的、C兼容的、以null结尾的字符串,中间没有null字节。

这种数据类型的目的是基于 Rust 的字节切片或 vector 数组生成 C 语言兼容的字符串。这种类型的实例需要确保字节数据中间不包含内部 0 字节(“null字符”),最后一个字节为0(“null终止符”)。
CString 与 &CStr 的关系就像 String 和 &str 的关系一样:CString、String 自身拥有字符串数据,而 &CStr、&str 只是借用数据而已。

3.输出指向 C 字符串的裸指针

CString 基于 Deref trait 实现了as_ptr方法。该方法给出一个 *const c_char 类型的指针,可以把这个指针传递给外部能够处理 null结尾的字符串的函数,例如 C 语言的 strdup() 函数。如果 C 语言代码往该指针所知的内存写入数据,将导致无法预测的结果。因为 C 语言所接受的这样的裸指针不包含字符串长度信息。

4.输出 C 字符串的切片

也可以使用 CString::as_bytes 方法从 CString 获取 &[u8] 切片。以这种方式生成的切片不包含尾部 null 终止符。这在调用一个外部函数时非常有用,该函数接受一个不一定以 null结尾的 *const u8参数,再加上另一个字符串长度的参数,比如 C 的 strndup()。当然,您可以使用 len 方法获得切片的长度。
如果想得到一个以 null 结尾的 &[u8] 切片,可以使用 CString::as_bytes_with_nul 方法。
无论获得 null 结尾的,还是没有 null 结尾的切片,都可以调用切片的 as_ptr 方法获得只读的裸指针,以便传递给外部函数使用。

三、综合比较

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72013.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElementUI分页的实现

官网地址&#xff1a;Element - The worlds most popular Vue UI framework 第一步&#xff1a;拷贝你喜欢的分页类型放在你的组件页面需要用到的分页位置 <el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-p…

记一次:request请求总结

前言&#xff1a;和前端联调的时候发现前端人员请求的方式不对&#xff0c;固做此总结问题&#xff1a;request请求方式有多少种&#xff1f;答&#xff1a;Java后端查看有8种&#xff0c;spring-web中的java枚举图如下而使用PostMan查看有15种&#xff0c;如下图GET&#xff0…

【重点掌握】Java基础之Javaweb核心技术详解

都说一入Java深似海&#xff0c;从此代码是爱人&#xff0c;但是学习的过程却从来都不轻松。当下&#xff0c;越来越多的互联网企业&#xff0c;招聘Java工程师时&#xff0c;明确写道需熟练掌握JavaWeb技术。作为衔接前后端的重要一环&#xff0c;JavaWeb技术已成为程序员向大…

火热报名 | DockQuery 1.2 beta版本体验官开启招募!

DockQuery是什么&#xff1f; DockQuery 代号「天狼」&#xff0c;是图尔兹全新自研的一款专业新型数据库桌面客户端&#xff0c;专为信创背景下国内外数据库开发/管理而设计&#xff0c;全面覆盖信创数据库目录、支持国内外操作系统。 目前&#xff0c;DockQuery 仅以社区版…

【教程】GitBook Editor编写电子书

GitBook Editor电子书编写说明1、安装软件2、创建文档3、编辑文档4、生成电子书1、安装软件 下载并安装GitBook Editor软件&#xff0c;网上资源很多&#xff0c;根据自己系统选用即可 官网参考&#xff1a;GitBook - Where technical teams document. 2、创建文档 1&#xf…

Talk | 清华大学交叉信息研究院助理教授杜韬:利用计算方法探究流固耦合

本期为TechBeat人工智能社区第474期线上Talk&#xff01; 北京时间2月15日(周三)20:00&#xff0c;清华大学交叉信息研究院助理教授——杜韬的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “利用计算方法探究流固耦合”&#xff0c;届时将介绍流固…

HTTP与HTTPS原理

目录 HTTP 协议背景 协议格式 请求行 请求报头 请求正文&#xff08;有效载荷&#xff09; 响应行 HTTPS原理 协议背景 什么是加密&#xff1f; 为什么要加密&#xff1f; 加密方式 数据摘要&#xff08;数据指纹&#xff09; 协议加密方案实现探究 方案一&#xff1a;只使用对…

【云原生】初识Kubernetes的理论基础

一、kubernetes概述 1.1 kubernetes介绍 K8S的全称为Kubernetes (K12345678S)&#xff0c;首字母与尾字母中间有8个字母&#xff0c;缩写为K8S 作用 用于自动部署、扩展和管理“容器化(containerized) 应用程序”的开源系统。可以理解成K8S是负责自动化运维管理多个容器化程序…

【云原生】k8s之Yaml文件详解

一、K8S支持的文件格式 kubernetes支持YAML和JSON文件格式管理资源对象。 JSON格式&#xff1a;主要用于api接口之间消息的传递YAML格式&#xff1a;用于配置和管理&#xff0c;YAML是一种简洁的非标记性语言&#xff0c;内容格式人性化&#xff0c;较易读 1、yaml和json的主…

[Golang实战]github.io部署个人博客hugo[新手开箱可用][小白教程]

[Golang实战]github.io部署个人博客hugo[新手开箱可用][小白教程]1.新手教程(小白也能学会)2.开始准备2.1myBlog是hugo的项目1.安装Hugo2.创建hugo项目2.2 xxxx.github.io是github.io中规定的pages项目3.成功部署4.TODO自动化workflows部署github.io1.新手教程(小白也能学会) …

分析| 2023年移动开发平台的发展空间

春节过后返工已经过月&#xff0c;许多移动开发领域的企业都在忙着做技术调研与选型。在此之前&#xff0c;不如先回顾一下2022年的市场趋势&#xff0c;再结合好的移动开发平台的标准&#xff0c;从中窥见2023年的发展前景。 Gartner十大战略技术趋势 全球权威咨询机构Gartne…

分析称勒索攻击在非洲、中东与中国增长最快

Orange Cyberdefense&#xff08;OCD&#xff09;于 2022 年 12 月 1 日发布了最新的网络威胁年度报告。报告中指出&#xff0c;网络勒索仍然是头号威胁 &#xff0c;也逐渐泛滥到世界各地。 报告中的网络威胁指的是企业网络中的某些资产被包括勒索软件在内的攻击进行勒索&…

2022-06-16_555时基的迷人历史和先天缺陷!

https://www.eet-china.com/news/magazine220608.html 555时基的迷人历史和先天缺陷&#xff01; 发布于2022-06-16 03:39:12 LARRY STABILE 流行数十年的555时基&#xff0c;业内不知晓的工程师应该寥寥无几&#xff01;几乎所有的数字电路教材中&#xff0c;都有该芯片的身影…

LeetCode 周赛 333,你管这叫 Medium 难度?

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 大家好&#xff0c;我是小彭。 上周是 LeetCode 第 333 场周赛&#xff0c;你参加了吗&#xff1f;这场周赛质量很高&#xff0c;但难度标得不对&#xff0c;我真的会谢。算法…

基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计

2.1 需求分析 本课题以龙芯 2K1000 处理器为嵌入式系统的处理器&#xff0c;需要实现一个完成的嵌 入式软件系统&#xff0c;系统能够正常启动并可以稳定运行嵌入式 Linux。设计网络设备驱 动&#xff0c;可以实现板卡与其他网络设备之间的网络连接和文件传输。设计 PCIE 设备驱…

重温一下C#的时间类型,并简单写一个定时器功能

&#x1f389;&#x1f389; 时间是一个非常抽象的概念&#xff0c;本篇文章我们不深究目前电脑上的时候是如何保持全网同步。主要是讲讲在使用C#编程语言里的时间类型。最后使用定时任务简单写一个提醒功能&#xff0c;比如&#xff1a;每天10点准时打开一次csdn首页&#xff…

yolov5源码解读--数据处理模块

yolov5源码解读--数据处理模块加载数据读取图片加载标签马赛克数据增强图片标签其他的数据增强变图像变标签__getitem__构建Batch加载数据 create_dataloader 跳转到datasets.py文件中&#xff0c;可以看到支持输入的文件类型非常丰富。。 回归正题 跳转LoadImagesAndLabel…

分析JEP 290机制的Java实现

简介 https://openjdk.org/jeps/290 Filter Incoming Serialization Data过滤传入的序列化数据 JEP290是Java官方提供的一套来防御反序列化的机制&#xff0c;其核心在于提供了一个ObjectInputFilter接口&#xff0c;通过设置filter对象&#xff0c;然后在反序列化&#xff…

c盘系统盘满了,无损扩容

磁盘管理 计算机-管理-磁盘管理 diskmgmt.msc1.选中c盘&#xff0c;右键选择扩展卷&#xff0c;如果是灰色&#xff0c;表示无法扩展 注意&#xff1a; 未分配区域不在同一磁盘&#xff0c;无法分配&#xff1b; 物理上不挨着的区域&#xff0c;无法分配&#xff1b; 2.把与c…

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建

【Spring Cloud Alibaba】003-Nacos 概述与单机搭建 文章目录【Spring Cloud Alibaba】003-Nacos 概述与单机搭建一、Nacos 概述0、新技术学习思路推荐1、什么是 Nacos2、架构图架构图架构图信息二、Nacos 单机搭建1、下载与启动下载地址编辑 startup.cmd 文件下面对两种模式的…