CString ve CStr
- Rust kursu
- İleri seviye
- Ders 38/81
- 4 dk
CString ve CStr ile C string dönüşümü yaparsın.
CString ve CStr
C dizeleri boş bayt (\0) ile biten bayt dizileridir; Rust dizeleri ise uzunluğunu bilir ve içinde \0 olabilir. Köprü iki türdür:
CString: sahip olunan, sonu\0ile biten dize; Rust'tan C'ye göndermek için.CStr: ödünç alınmış C dizesi; C'den gelen işaretçiyi okumak için.
use std::ffi::{CStr, CString};
let c = CString::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) }; // 7
let s = CStr::from_bytes_with_nul(b"rust\0").unwrap();
println!("{}", s.to_str().unwrap()); // rustSık yapılan hata: sarkan işaretçi
as_ptr ile alınan işaretçi yalnızca CString yaşadığı sürece geçerlidir. Geçici bir değerden işaretçi almak sarkan işaretçi üretir:
// YANLIŞ: CString hemen bırakılır, p geçersiz kalır
let p = CString::new("x").unwrap().as_ptr();
// DOĞRU: önce değişkene bağla
let c = CString::new("x").unwrap();
let p = c.as_ptr(); // c yaşadıkça geçerliSahipliği C'ye devretmek için into_raw, geri almak için CString::from_raw kullanılır.
Uygulama C dizeleri
C'nin strlen fonksiyonunu bildir. CString::new("merhaba") uzunluğunu strlen ile al; CStr::from_bytes_with_nul(b"rust\0") değerini &str'ye çevir; CString::new("a\0b").is_err() sonucunu bul. Üçünü boşlukla yazdır.
Başlangıç kodu
use std::ffi::{c_char, CStr, CString};
fn main() {
// buraya yaz
}Örnek çözüm
use std::ffi::{c_char, CStr, CString};
unsafe extern "C" {
fn strlen(s: *const c_char) -> usize;
}
fn main() {
let c = CString::new("merhaba").unwrap();
// SAFETY: c geçerli, sonu boş baytla biten bir dizedir.
let n = unsafe { strlen(c.as_ptr()) };
let s = CStr::from_bytes_with_nul(b"rust\0").unwrap();
let hata = CString::new("a\0b").is_err();
println!("{} {} {}", n, s.to_str().unwrap(), hata);
}Beklenen çıktı
7 rust true
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 <code>CString::new("a\0b")</code> neden hata verir?
- b geçersiz
- Çok kısa
- Hata vermez
- İçteki \0, C tarafında dizeyi erken bitirirdi Doğru cevap
Açıklama: CString::new içte boş bayt bulursa NulError döndürür; böylece sessiz kesilme önlenir.
2 C dizesi oluştur
let c = ____::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) };
let c = CString::new("merhaba").unwrap();
let n = unsafe { strlen(c.as_ptr()) };
Açıklama: CString Rust'tan C'ye dize göndermek içindir.
3 Tür ve yönü
| Kavram | Anlamı |
|---|---|
CString |
Rust → C (sahip) |
CStr |
C → Rust (ödünç) |
as_ptr() |
*const c_char |
into_raw() |
Sahipliği C'ye ver |